<!DOCTYPE html>


<html lang="en">


<head>
  <meta charset="utf-8" />
    
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
  <title>
     
  </title>
  <meta name="generator" content="hexo-theme-ayer">
  
  <link rel="shortcut icon" href="/favicon.ico" />
  
  
<link rel="stylesheet" href="/dist/main.css">

  
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Shen-Yu/cdn/css/remixicon.min.css">

  
<link rel="stylesheet" href="/css/custom.css">

  
  
<script src="https://cdn.jsdelivr.net/npm/pace-js@1.0.2/pace.min.js"></script>

  
  

  

</head>

</html>

<body>
  <div id="app">
    
      
      <canvas width="1777" height="841"
        style="position: fixed; left: 0px; top: 0px; z-index: 99999; pointer-events: none;"></canvas>
      
    <main class="content on">
      
<section class="cover">
    
  <div class="cover-frame">
    <div class="bg-box">
      <img src="/images/82752296_p0.jpg" alt="image frame" />
    </div>
    <div class="cover-inner text-center text-white">
      <h1><a href="/">Doreen&#39;s Blog</a></h1>
      <div id="subtitle-box">
        
        <span id="subtitle"></span>
        
      </div>
      <div>
        
      </div>
    </div>
  </div>
  <div class="cover-learn-more">
    <a href="javascript:void(0)" class="anchor"><i class="ri-arrow-down-line"></i></a>
  </div>
</section>



<script src="https://cdn.jsdelivr.net/npm/typed.js@2.0.11/lib/typed.min.js"></script>


<!-- Subtitle -->

  <script>
    try {
      var typed = new Typed("#subtitle", {
        strings: ['一切都会好的，城南的花都开了', '今晚的月色真美', '注重过程，别在乎结果'],
        startDelay: 0,
        typeSpeed: 200,
        loop: true,
        backSpeed: 100,
        showCursor: true
      });
    } catch (err) {
      console.log(err)
    }
  </script>
  
<div id="main">
  <section class="outer">
  
  

<div class="notice" style="margin-top:50px">
    <i class="ri-heart-fill"></i>
    <div class="notice-content" id="broad"></div>
</div>
<script type="text/javascript">
    fetch('https://v1.hitokoto.cn')
        .then(response => response.json())
        .then(data => {
            document.getElementById("broad").innerHTML = data.hitokoto;
        })
        .catch(console.error)
</script>

<style>
    .notice {
        padding: 20px;
        border: 1px dashed #e6e6e6;
        color: #969696;
        position: relative;
        display: inline-block;
        width: 100%;
        background: #fbfbfb50;
        border-radius: 10px;
    }

    .notice i {
        float: left;
        color: #999;
        font-size: 16px;
        padding-right: 10px;
        vertical-align: middle;
        margin-top: -2px;
    }

    .notice-content {
        display: initial;
        vertical-align: middle;
    }
</style>
  
  <article class="articles">
    
    
    
    
    <article
  id="post-JavaScript"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2023/11/18/JavaScript/"
    >JavaScript</a> 
</h2>
 

    </header>
     
    <div class="article-meta">
      <a href="/2023/11/18/JavaScript/" class="article-date">
  <time datetime="2023-11-18T04:21:42.000Z" itemprop="datePublished">2023-11-18</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/JavaScript/">JavaScript</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <h1 id="回调地狱"><a href="#回调地狱" class="headerlink" title="回调地狱"></a>回调地狱</h1><blockquote>
<p>回调函数嵌套回调函数，为了能按顺序执行异步任务 （可读性差</p>
</blockquote>
<h1 id="Promise"><a href="#Promise" class="headerlink" title="Promise"></a>Promise</h1><blockquote>
<p>js对象，异步编程的解决方案，是一个构造函数，自身有resolve、reject等方法，原型上有then、catch方法</p>
</blockquote>
<h2 id="特点"><a href="#特点" class="headerlink" title="特点"></a>特点</h2><ol>
<li>状态只受异步操作的结果影响，不受外界影响。<code>pending</code>、<code>rejected</code>、<code>fulfilled</code></li>
<li>一旦状态改变，不会再改变。</li>
<li>链式调用</li>
</ol>
<h1 id="async-await"><a href="#async-await" class="headerlink" title="async/await"></a>async/await</h1><blockquote>
<p><code>async</code> 函数返回一个 <code>promise</code> 对象，可以用 <code>then</code> 方法添加回调函数。当执行的时候，一旦遇到 <code>await</code> 就先返回，等到触发的异步操作完成，再执行函数体后面的语句</p>
</blockquote>
<h2 id="特点-1"><a href="#特点-1" class="headerlink" title="特点"></a>特点</h2><ol>
<li>同步代码编写方式。顺序执行就像写同步代码，符合编码习惯</li>
<li>多个参数传递。</li>
<li>同步代码和异步代码可以一起编写。</li>
<li>对 <code>promise</code> 的优化</li>
</ol>
<h1 id="BOM"><a href="#BOM" class="headerlink" title="BOM"></a>BOM</h1><ul>
<li><p><code>navigator</code>: 获取浏览器特性，识别客户端</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> ua = navigator.userAgent</span><br><span class="line"><span class="keyword">const</span> isChrome = ua.indexOf(<span class="string">&#x27;Chrome&#x27;</span>)</span><br></pre></td></tr></table></figure>
</li>
<li><p><code>screen</code>: 获取屏幕相关信息 <code>screen.height</code> , <code>screen.width</code></p>
</li>
<li><p><code>location</code>: 获取网址、协议、path、参数、hash等</p>
</li>
<li><p><code>history</code>: 调用浏览器前进、后退功能等</p>
</li>
</ul>
<h1 id="let-const-var-作用域"><a href="#let-const-var-作用域" class="headerlink" title="let const var 作用域"></a>let const var 作用域</h1><blockquote>
<p>在全局作用域中， <code>let</code> 和 <code>const</code> 声明的全局变量，存储在了一个块级作用域 <code>script</code> 中。 <code>var</code> 声明的变量， <code>function</code> 声明的函数直接挂载到了<code>全局对象 (global) 的属性上</code></p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> b = <span class="string">&#x27;let b&#x27;</span></span><br><span class="line"><span class="keyword">var</span> a = <span class="string">&#x27;var a&#x27;</span></span><br><span class="line"><span class="keyword">const</span> c = <span class="string">&#x27;const c&#x27;</span></span><br><span class="line"><span class="keyword">var</span> funA = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;hello&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> funB = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;world&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fun</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;-&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//          var a, undefined, undefined, -, hello, Error ... not a function</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="built_in">this</span>.a, <span class="built_in">this</span>.b, <span class="built_in">this</span>.c, <span class="built_in">this</span>.fun(), <span class="built_in">this</span>.funA(), <span class="built_in">this</span>.funB())</span><br><span class="line"></span><br><span class="line"><span class="comment">// 正常输出，先执行函数 再输出变量</span></span><br><span class="line"><span class="built_in">console</span>.log(a, b, c, fun(), funA(), funB())</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p><img src="https://i.postimg.cc/Njz2qqbh/1699858887446.png"></p>
<h1 id="let-const-var-使用场景"><a href="#let-const-var-使用场景" class="headerlink" title="let const var 使用场景"></a>let const var 使用场景</h1><blockquote>
<p>let、const、var 用于声明变量的关键字</p>
</blockquote>
<ol>
<li>var：</li>
</ol>
<ul>
<li>可以声明全局变量和局部变量。</li>
<li>变量声明提升，可以在声明之前使用，但是值为 undefined。</li>
<li>可以重复声明同一个变量。</li>
</ul>
<ol start="2">
<li>let：</li>
</ol>
<ul>
<li>块级作用域的变量声明方式，只在语句块内有效。</li>
<li>不允许重复声明同一个变量。</li>
<li>不会像 var 一样存在变量声明提升的问题。</li>
</ul>
<ol start="3">
<li>const：</li>
</ol>
<ul>
<li>声明一个只读常量，不允许修改。</li>
<li>也是块级作用域的方式声明变量，只在语句块内有效。</li>
<li>不允许重复声明同一个变量。</li>
</ul>
<p>总的来说，推荐使用 <code>const</code> 和 <code>let</code> 声明变量，因为它们的作用域更加明确，可以有效避免变量的问题。</p>
<ul>
<li><p><code>const</code> 适合声明不需要修改的常量，</p>
</li>
<li><p><code>let</code> 则适合一般的变量声明。</p>
</li>
<li><p>而在一些特殊场景下，<code>var</code> 也可以用来声明变量。 </p>
<p>  在特定场景下，使用 var 声明变量也是可以的，虽然这种情况很少：</p>
<ol>
<li><p>在<code>全局作用域</code>下声明变量，这时候使用 var 会更为方便。</p>
</li>
<li><p>在<code>函数</code>中声明变量时，如果希望变量的<code>作用域能够扩展到整个函数</code>，那么使用 var 声明变量就是比较合适的。</p>
</li>
<li><p>如果需要把<code>同名变量声明在某个嵌套的作用域内</code>，同时又不希望它被外部的作用域访问到，那么使用 var 就是比较好的选择。</p>
<blockquote>
<p>需要注意的是，在使用 var 的时候，要特别小心变量提升（Hoisting），也就是在变量还没有被声明时就可以使用的问题。<br>因此，建议在 JavaScript 中尽量使用 let 或 const 来声明变量，尤其是在块级作用域中声明变量时。</p>
</blockquote>
</li>
</ol>
</li>
</ul>
<h1 id="数据类型判断"><a href="#数据类型判断" class="headerlink" title="数据类型判断"></a>数据类型判断</h1><blockquote>
<p>基础数据类型：string、number、boolean、null、undefined、symbol<br>  引用数据类型：object (function、object、array)</p>
</blockquote>
<ul>
<li><code>原始数据类型</code>在内存中是<code>栈</code>存储，<code>引用类型</code>是<code>堆</code>存储</li>
<li>栈（stack）为自动分配的内存空间，它由系统自动释放</li>
<li>堆（heap）则是动态分配的内存，大小不定也不会自动释放</li>
<li>在内存中存储方式的不同导致了原始数据类型不可变</li>
<li>原始数据类型和引用数据类型做赋值操作一个是<code>传值</code>一个是<code>传址</code></li>
</ul>
<h2 id="typeof"><a href="#typeof" class="headerlink" title="typeof"></a>typeof</h2><blockquote>
<p>用于判断基础数据类型</p>
</blockquote>
<ul>
<li>对于<code>基础类型</code>，除 <code>null</code> 以外，均可以正确返回</li>
<li>对于<code>引用类型</code>，除 <code>function</code> 以外，均返回 <code>object</code> </li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typeof</span> <span class="string">&#x27;&#x27;</span> <span class="comment">// string</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="number">1</span> <span class="comment">// number</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="built_in">Symbol</span>() <span class="comment">// symbol</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="literal">true</span> <span class="comment">// boolean</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="literal">undefined</span> <span class="comment">// undefined</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">typeof</span> <span class="literal">null</span> <span class="comment">// object ×</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">typeof</span> [] <span class="comment">// object</span></span><br><span class="line"><span class="keyword">typeof</span> &#123;&#125; <span class="comment">// object</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="keyword">new</span> <span class="built_in">Function</span>() <span class="comment">// function</span></span><br></pre></td></tr></table></figure>

<h2 id="instanceof"><a href="#instanceof" class="headerlink" title="instanceof"></a>instanceof</h2><blockquote>
<p>用于判断引用数据类型 （判断两个对象是否属于实例关系，<code>不能判断一个对象实例具体属于哪种类型</code><br>xx.<strong>proto</strong> =&gt; XX.prototype // 最终都指向 null </p>
</blockquote>
<p>eg: <code>[].__proto__ -&gt; Array.prototype -&gt; Object.prototype -&gt; null</code></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">[] <span class="keyword">instanceof</span> <span class="built_in">Array</span> <span class="comment">// true</span></span><br><span class="line">[] <span class="keyword">instanceof</span> <span class="built_in">Object</span> <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line">&#123;&#125; <span class="keyword">instanceof</span> <span class="built_in">Object</span> <span class="comment">// true</span></span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Date</span>() <span class="keyword">instanceof</span> <span class="built_in">Date</span> <span class="comment">// true</span></span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Function</span>() <span class="keyword">instanceof</span> <span class="built_in">Function</span> <span class="comment">// true</span></span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Function</span>() <span class="keyword">instanceof</span> <span class="built_in">Object</span> <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line"><span class="number">1</span> <span class="keyword">instanceof</span> <span class="built_in">Number</span> <span class="comment">// false</span></span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Number</span>(<span class="number">1</span>) <span class="keyword">instanceof</span> <span class="built_in">Number</span> <span class="comment">// true</span></span><br><span class="line"><span class="number">1</span> == <span class="keyword">new</span> <span class="built_in">Number</span>(<span class="number">1</span>)</span><br></pre></td></tr></table></figure>

<h2 id="constructor-NaN"><a href="#constructor-NaN" class="headerlink" title="constructor"></a>constructor</h2><blockquote>
<p>用于判断引用数据类型，原型对象内包含一个 <code>constructor</code> 构造器，指向的是构造函数 <code>（对 null、undefined 无效）</code></p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> num = <span class="number">1</span>,str = <span class="string">&#x27;&#x27;</span>,obj = &#123;&#125;</span><br><span class="line"></span><br><span class="line">num.__proto__.constructor === <span class="built_in">Number</span> <span class="comment">// true</span></span><br><span class="line">num.__proto__.constructor === <span class="built_in">Object</span> <span class="comment">// false</span></span><br><span class="line"></span><br><span class="line">str.__proto__.constructor === <span class="built_in">String</span> <span class="comment">// true</span></span><br><span class="line">obj.__proto__.constructor === <span class="built_in">Object</span> <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<h2 id="Object-prototype-toString-最严谨的方法"><a href="#Object-prototype-toString-最严谨的方法" class="headerlink" title="Object.prototype.toString (最严谨的方法)"></a>Object.prototype.toString (最严谨的方法)</h2><blockquote>
<p>内置转换方法判断类型</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> num = <span class="number">1</span></span><br><span class="line"><span class="keyword">var</span> str = <span class="string">&#x27;abc&#x27;</span></span><br><span class="line"><span class="keyword">var</span> arr = []</span><br><span class="line"><span class="keyword">var</span> obj = &#123;&#125;</span><br><span class="line"><span class="keyword">var</span> nul = <span class="literal">null</span></span><br><span class="line"><span class="keyword">var</span> unde</span><br><span class="line"><span class="keyword">var</span> bool = <span class="literal">true</span></span><br><span class="line"><span class="keyword">var</span> foo = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString() <span class="comment">// [object Object]</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(str) <span class="comment">// [object String]</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(num) <span class="comment">// [object Number]</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(arr) <span class="comment">// [object Array]</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(obj) <span class="comment">// [object Object]</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(nul) <span class="comment">// [object Null]</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(unde) <span class="comment">// [object Undefined]</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(bool) <span class="comment">// [object Boolean]</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(foo) <span class="comment">// [object Function]</span></span><br><span class="line"></span><br></pre></td></tr></table></figure> 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
    </footer>
  </div>

    
 
   
</article>

    
    <article
  id="post-flvjs"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2023/10/21/flvjs/"
    >Flvjs</a> 
</h2>
 

    </header>
     
    <div class="article-meta">
      <a href="/2023/10/21/flvjs/" class="article-date">
  <time datetime="2023-10-21T04:21:42.000Z" itemprop="datePublished">2023-10-21</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/%E8%A7%86%E9%A2%91%E7%9B%B8%E5%85%B3/">视频相关</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <h2 id="flv-js"><a href="#flv-js" class="headerlink" title="flv.js"></a><a target="_blank" rel="noopener" href="http://bilibili.github.io/flv.js">flv.js</a></h2><p><a target="_blank" rel="noopener" href="https://www.jianshu.com/p/b58356b465c4">中文文档</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/TurtleOrange/article/details/119147481">实用的文档</a></p>
<p><a target="_blank" rel="noopener" href="http://events.jianshu.io/p/681239401c7e">解决跳帧、断流问题文档</a></p>
<blockquote>
<p>一个可以在HTML5视频中播放.flv视频格式的JavaScript库</p>
</blockquote>
<h3 id="API"><a href="#API" class="headerlink" title="API"></a><a target="_blank" rel="noopener" href="http://bilibili.github.io/flv.js/docs/api.html">API</a></h3><h3 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h3><ol>
<li>安装依赖</li>
</ol>
<blockquote>
<p>npm i –save flv.js</p>
</blockquote>
<ol start="2">
<li>在文件中引入依赖</li>
</ol>
<blockquote>
<p>import flvjs from ‘flv.js’</p>
</blockquote>
<ol start="3">
<li>初始化播放器实例，并播放</li>
</ol>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">video</span> <span class="attr">id</span>=<span class="string">&#x27;video&#x27;</span> <span class="attr">controls</span>&gt;</span><span class="tag">&lt;/<span class="name">video</span>&gt;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">const</span> videoDom = <span class="built_in">document</span>.getElementById(<span class="string">&#x27;video&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (flvjs.isSupported()) &#123; <span class="comment">// 判断浏览器是否支持flvjs</span></span><br><span class="line">  <span class="keyword">const</span> flvPlayer = flvjs.createPlayer(&#123;</span><br><span class="line">      type: <span class="string">&#x27;flv&#x27;</span>,</span><br><span class="line">      url: <span class="string">&#x27;&#x27;</span>,</span><br><span class="line">      isLive: <span class="literal">true</span>,</span><br><span class="line">      hasAudio: <span class="literal">false</span>,</span><br><span class="line">      hasVideo: <span class="literal">true</span>,</span><br><span class="line">      duration: <span class="number">0</span>,</span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">      enableWorker: <span class="literal">false</span>,</span><br><span class="line">      autoCleanupSourceBuffer: <span class="literal">true</span>, <span class="comment">// 对SourceBuffer进行自动清理</span></span><br><span class="line">      autoCleanupMaxBackwardDuration: <span class="number">12</span>, <span class="comment">// 当向后缓冲区持续时间超过此值（以秒为单位）时，请对SourceBuffer进行自动清理</span></span><br><span class="line">      autoCleanupMinBackwardDuration: <span class="number">8</span>, <span class="comment">// 指示进行自动清除时为反向缓冲区保留的持续时间（以秒为单位）。</span></span><br><span class="line">      enableStashBuffer: <span class="literal">false</span>, <span class="comment">// 关闭IO隐藏缓冲区</span></span><br><span class="line">      isLive: <span class="literal">true</span>,</span><br><span class="line">      lazyLoad: <span class="literal">false</span>,</span><br><span class="line">      reuseRedirectedURL: <span class="literal">true</span>     </span><br><span class="line">      &#125;)</span><br><span class="line">      flvPlayer.attachMediaElement(videoDom)</span><br><span class="line">      flvPlayer.load()</span><br><span class="line">      flvPlayer.play()</span><br><span class="line"></span><br><span class="line">      <span class="comment">// 监听数据源是否加载完成</span></span><br><span class="line">      flvPlayer.on(flvjs.Events.LOADING_COMPLETE, <span class="function">(<span class="params">res</span>) =&gt;</span> &#123;</span><br><span class="line">          <span class="keyword">if</span> (!flvPlayer._receivedCanPlay) &#123;</span><br><span class="line">            <span class="comment">// 不能播放 销毁</span></span><br><span class="line">            flvPlayer.pause()</span><br><span class="line">            flvPlayer.unload()</span><br><span class="line">            flvPlayer.detachMediaElement();</span><br><span class="line">            flvPlayer.destroy();</span><br><span class="line">            <span class="comment">// message.error(&#x27;视频资源获取失败&#x27;)</span></span><br><span class="line">          &#125;</span><br><span class="line">        &#125;)</span><br><span class="line"></span><br><span class="line">      <span class="comment">// 所有异常捕获（播放途中断流、网络错误等）</span></span><br><span class="line">      flvPlayer.on(flvjs.Events.ERROR, <span class="function">(<span class="params">errorType, errorDetail, errorInfo</span>) =&gt;</span> &#123;</span><br><span class="line">          flvPlayer.pause()</span><br><span class="line">          flvPlayer.unload()</span><br><span class="line">          flvPlayer.detachMediaElement();</span><br><span class="line">          flvPlayer.destroy();</span><br><span class="line">        &#125;)</span><br><span class="line"></span><br><span class="line">      <span class="comment">// 关闭异常</span></span><br><span class="line">      flvPlayer.off(flvjs.Events.ERROR, <span class="function"><span class="params">err</span> =&gt;</span> &#123;</span><br><span class="line">          <span class="built_in">console</span>.log(<span class="string">&#x27;--off异常&#x27;</span>, err)</span><br><span class="line">      &#125;)</span><br><span class="line"></span><br><span class="line">      <span class="comment">// 监听数据流请求 只要流在请求就一直监听 （追针应该就是通过定时器写在这里实现的）</span></span><br><span class="line">      flvPlayer.on(flvjs.Events.STATISTICS_INFO, <span class="function">(<span class="params">res</span>) =&gt;</span> &#123;</span><br><span class="line">          <span class="built_in">console</span>.log(<span class="string">&#x27;请求数据信息&#x27;</span>)</span><br><span class="line">      &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">      </span><br></pre></td></tr></table></figure>

<ol start="4">
<li>跳帧处理</li>
</ol>
<blockquote>
<p>通过改变视频的当前时间来实现<br><code>buffered</code> 属性返回 <code>TimeRanges</code> 对象,表示音频/视频的已缓冲部分</p>
</blockquote>
<p><em><code>TimeRanges</code> 对象的属性：</em></p>
<ul>
<li><code>length</code> - 获得音频/视频中已缓冲范围的数量</li>
<li><code>start(index)</code> - 获得某个已缓冲范围的开始位置</li>
<li><code>end(index)</code> - 获得某个已缓冲范围的结束位置</li>
<li>注释：第一个缓冲范围的下标是 0</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> clearBufferToPlay = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (flvPlayer &amp;&amp; flvPlayer.buffered &amp;&amp; flvPlayer.buffered.length) &#123;</span><br><span class="line">        <span class="keyword">const</span> end = flvPlayer.buffered.end(<span class="number">0</span>)</span><br><span class="line">        <span class="keyword">const</span> diff = end - flvPlayer.currentTime;</span><br><span class="line">        <span class="keyword">if</span> (diff &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            flvPlayer.currentTime = end - <span class="number">0.00001</span> <span class="comment">// 直接等于end会加载不出来</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<ol start="5">
<li>追针处理</li>
</ol>
<blockquote>
<p>改变视频播放的速率来实现</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> changeSpeadToPlay = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (flvPlayer &amp;&amp; flvPlayer.buffered &amp;&amp; flvPlayer.buffered.length) &#123;</span><br><span class="line">        <span class="keyword">const</span> end = flvPlayer.buffered.end(<span class="number">0</span>)</span><br><span class="line">        <span class="keyword">const</span> diff = end - flvPlayer.currentTime;</span><br><span class="line">        <span class="keyword">if</span> (diff &gt; <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="comment">// 大于一秒开始倍速播放</span></span><br><span class="line">            videoElement.playbackRate = <span class="number">1.1</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (diff &lt;= <span class="number">0.5</span>) &#123;</span><br><span class="line">            videoElement.playbackRate = <span class="number">1</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ol start="6">
<li>异常处理</li>
</ol>
<blockquote>
<p>后端转流后会出现第一帧卡帧的情况、追针和跳帧在流不稳定的情况下容易出问题</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">  flvPlayerList[index].on(flvjs.Events.STATISTICS_INFO, <span class="function">(<span class="params">res</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (res.decodedFrames === <span class="number">0</span>) &#123;</span><br><span class="line">      <span class="comment">// TODO 画面卡顿重连</span></span><br><span class="line">      stuckCount.value[index] = stuckCount.value[index] ? stuckCount.value[index] + <span class="number">1</span> : <span class="number">1</span></span><br><span class="line">      <span class="keyword">if</span> (stuckCount.value[index] &gt;= <span class="number">30</span>) &#123;</span><br><span class="line">        setAllPlayFlag(<span class="literal">false</span>)</span><br><span class="line">        <span class="comment">// TODO 是否需要重连</span></span><br><span class="line">        <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">          stuckCount.value[index] = <span class="number">0</span></span><br><span class="line">          handleVideoStatusChange(index, <span class="literal">true</span>)</span><br><span class="line">          playerList[index].addEventListener(<span class="string">&#x27;loadedmetadata&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">            setAllPlayFlag(isAllPlayStatus(currentPage, defaultSize))</span><br><span class="line">            &#125;)</span><br><span class="line">            <span class="built_in">console</span>.log(<span class="string">&#x27;---画面卡顿重连&#x27;</span>)</span><br><span class="line">            &#125;, <span class="number">1000</span>);</span><br><span class="line">          &#125;</span><br><span class="line">          <span class="built_in">console</span>.log(<span class="string">`%c STATISTICS_INFO loading  <span class="subst">$&#123;index&#125;</span> , count:<span class="subst">$&#123;stuckCount.value[index]&#125;</span> <span class="subst">$&#123;playerList[index]?.paused&#125;</span>`</span>, <span class="string">&#x27;color:red&#x27;</span>)</span><br><span class="line">          &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            stuckCount.value[index] = <span class="number">0</span></span><br><span class="line">        &#125;</span><br><span class="line">      &#125;)</span><br><span class="line">    &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">      <span class="built_in">console</span>.log(<span class="string">&#x27;拉流异常捕获&#x27;</span>, err)</span><br><span class="line">  &#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> handleProgress = <span class="function">(<span class="params">index: number</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="comment">// 数据在请求但是画面不动</span></span><br><span class="line">  <span class="keyword">if</span> (playSt.value[index]) &#123;</span><br><span class="line">    <span class="keyword">if</span> (currentTimeCount.value[index] &amp;&amp; currentTimeCount.value[index].key == playerList[index].currentTime) &#123;</span><br><span class="line">      currentTimeCount.value[index].count++</span><br><span class="line">      <span class="keyword">if</span> (currentTimeCount.value[index].count &gt;= <span class="number">10</span>) &#123;</span><br><span class="line"></span><br><span class="line">        currentTimeCount.value[index] = <span class="literal">null</span></span><br><span class="line">        handleVideoStatusChange(index, <span class="literal">true</span>)</span><br><span class="line"></span><br><span class="line">        playerList[index].addEventListener(<span class="string">&#x27;loadedmetadata&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">          setAllPlayFlag(isAllPlayStatus(currentPage, defaultSize))</span><br><span class="line">        &#125;)</span><br><span class="line"></span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&#x27;%c 画面卡顿重连&#x27;</span>, <span class="string">&#x27;color:red&#x27;</span>)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      currentTimeCount.value[index] = &#123; <span class="attr">key</span>: playerList[index].currentTime ? playerList[index].currentTime : <span class="number">0</span> + <span class="string">&#x27;&#x27;</span>, <span class="attr">count</span>: <span class="number">1</span> &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="内存泄漏"><a href="#内存泄漏" class="headerlink" title="内存泄漏"></a>内存泄漏</h2><blockquote>
<p>文档提供的配置项设置了之后还是会内存泄漏，目前解决方法是 <code>reload()</code> 可以清除缓存、但是切换标签的时候会清空所有状态，只有在路由跳转的时候用一下</p>
</blockquote>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
    </footer>
  </div>

    
 
   
</article>

    
    <article
  id="post-fiber &amp; diff &amp; HOC"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2023/10/21/fiber%20&%20diff%20&%20HOC/"
    >【react】Fiber &amp; Diff &amp; HOC</a> 
</h2>
 

    </header>
     
    <div class="article-meta">
      <a href="/2023/10/21/fiber%20&%20diff%20&%20HOC/" class="article-date">
  <time datetime="2023-10-20T23:21:42.000Z" itemprop="datePublished">2023-10-21</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/react/">react</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <p><a target="_blank" rel="noopener" href="https://mp.weixin.qq.com/s/gaASCIVTuUfsM-cVP2teGw">原文</a> | <a target="_blank" rel="noopener" href="https://www.bilibili.com/video/BV1y94y1v7TL?p=10&vd_source=a56b31fb136d9787929c44f3b4e80c4f">视频</a></p>
<h1 id="fiber架构"><a href="#fiber架构" class="headerlink" title="fiber架构"></a>fiber架构</h1><blockquote>
<p>jsx -&gt; babel （转换成虚拟dom） -&gt; render (渲染到页面上，将vDom挂载到真实的dom)</p>
</blockquote>
<h2 id="为什么需要fiber"><a href="#为什么需要fiber" class="headerlink" title="为什么需要fiber"></a>为什么需要fiber</h2><p>vdom -&gt; dom （renderer 渲染器</p>
<p>reconciler diff vdom进行对比更新 （vdom-&gt;dom 是同步的过程</p>
<p>在 16 之前，<code>React</code> 是直接递归渲染 <code>vdom</code> 的，<code>setState</code> 会触发重新渲染，对比渲染出的新旧 <code>vdom</code>，对差异部分进行 <code>dom</code> 操作。</p>
<p>在 16 之后，为了优化性能，会先把 <code>vdom</code> 转换成 <code>fiber</code>，也就是从<code>树转换成链表</code>，然后再渲染。整体渲染流程分成了两个阶段：</p>
<ul>
<li><p><code>render</code> 阶段：从 <code>vdom</code> 转换成 <code>fiber</code>，并且对需要 <code>dom</code> 操作的节点打上 <code>effectTag</code> 的标记</p>
</li>
<li><p><code>commit</code> 阶段：对有 <code>effectTag</code> 标记的 <code>fiber</code> 节点进行 <code>dom</code> 操作，并执行所有的 <code>effect</code> 副作用函数。</p>
</li>
</ul>
<p>从 <code>vdom</code> 转成 <code>fiber</code> 的过程叫做 <code>reconcile</code>（调和），这个过程是<code>可以打断</code>的，由 <code>scheduler</code> 调度执行</p>
<p><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e3976e170f634ab4a8a79583b47236c1~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp"></p>
<p><strong>fiber就是解决同步更新耗时长的问题的</strong></p>
<h3 id="同步更新存在的问题-gt-怎么该进"><a href="#同步更新存在的问题-gt-怎么该进" class="headerlink" title="同步更新存在的问题 -&gt; 怎么该进"></a>同步更新存在的问题 -&gt; 怎么该进</h3><ol>
<li>同步不可中断 -&gt; 异步可中断</li>
<li>scheduler 中存在任务优先级</li>
</ol>
<p>fiber -&gt; <a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestIdleCallback">window.requestIdleCallback()</a>  解决该方法兼容性问题</p>
<blockquote>
<p><code>window.requestIdleCallback(callack,option)</code> 方法插入一个函数，这个函数将在浏览器空闲时期被调用。这使开发者能够在主事件循环上执行后台和低优先级工作，而不会影响延迟关键事件，如动画和输入响应。函数一般会按先进先调用的顺序执行，然而，如果回调函数指定了执行超时时间timeout，则有可能为了在超时前执行函数而打乱执行顺序。</p>
</blockquote>
<h3 id="解决的问题"><a href="#解决的问题" class="headerlink" title="解决的问题"></a>解决的问题</h3><ol>
<li>新的任务调度，有高优先级任务的时候将浏览器让出来，等浏览器空了在执行</li>
<li>新的数据结构，可以随时中断，下次进来可以接着执行</li>
</ol>
<p>节点 -&gt; 子节点 -&gt; 子节点 -&gt; 兄弟节点 -&gt; return父节点</p>
<h1 id="diff算法"><a href="#diff算法" class="headerlink" title="diff算法"></a>diff算法</h1><p><code>diff</code> 算法作用在 <code>reconcile</code> 阶段：</p>
<ul>
<li>第一次渲染不需要 <code>diff</code>，直接 <code>vdom</code> 转 <code>fiber</code>。</li>
<li>再次渲染的时候，会产生新的 <code>vdom</code>，这时候要和之前的 <code>fiber</code> 做下对比，决定怎么产生新的 <code>fiber</code>，<code>对可复用</code>的节点打上<code>修改的标记</code>，剩余的<code>旧节点</code>打上<code>删除标记</code>，<code>新节点</code>打上<code>新增标记</code>。</li>
</ul>
<h2 id="那为什么浏览器里要做-diff"><a href="#那为什么浏览器里要做-diff" class="headerlink" title="那为什么浏览器里要做 diff"></a>那为什么浏览器里要做 diff</h2><blockquote>
<p>因为 dom 创建的性能成本很高，如果不做 dom 的复用，那前端框架的性能就太差了。</p>
</blockquote>
<p>diff 算法的目的就是对比两次渲染结果，找到可复用的部分，然后剩下的该删除删除，该新增新增。</p>
<h2 id="具体实现"><a href="#具体实现" class="headerlink" title="具体实现"></a>具体实现</h2><p><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5e84df8ff27e4d62821d33ddb5da70bf~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp"></p>
<p>经过 reconcile 之后，会变成这样的 fiber 结构：<br><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bc7234f1527c4f87824d61c370acc3b3~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp"></p>
<p>再次渲染出 vdom 的时候，也要进行 vdom 转 fiber 的 reconcile 阶段，但是要尽量能复用之前的节点。</p>
<p>那怎么复用呢？</p>
<p>一一对比下不就行了？</p>
<p>先把之前的 fiber 节点放到一个 map 里，key 就是节点的 key：<br><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c05c69856a97458fa2152f7d0490d566~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp"></p>
<p>然后每个新的 vdom 都去这个 map 里查找下有没有可以复用的，找到了的话就移动过来，打上更新的 effectTag：<br>**( Q: 为什么标记的是更新 A: 不重新创建 dom，但是属性什么的还是要更新 )**<br><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f03c4886363642178b7fd39504a35e7b~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp"></p>
<p>这样遍历完 vdom 节点之后，map 里剩下一些，这些是不可复用的，那就删掉，打上删除的 effectTag；如果 vdom 中还有一些没找到复用节点的，就直接创建，打上新增的 effectTag</p>
<p><strong>核心就是找到可复用的节点，删掉剩下的旧节点，新节点新增。</strong></p>
<h1 id="技术总结"><a href="#技术总结" class="headerlink" title="技术总结"></a>技术总结</h1><p>浏览器下使用 <code>react-dom</code> 的渲染器，会先把 <code>vdom</code> 转成 <code>fiber</code>，找到需要更新 <code>dom</code> 的部分，打上增删改的 <code>effectTag</code> 标记，这个过程叫做 <code>reconcile</code>，可以打断，由 <code>scheducler</code> 调度执行。<code>reconcile</code> 结束之后一次性根据 <code>effectTag</code> 更新 <code>dom</code>，叫做 <code>commit</code>。</p>
<p>这就是 react 的基于 fiber 的渲染流程，分成 <code>render（reconcile + schedule）</code>、<code>commit</code> 两个阶段。</p>
<p>当渲染完一次，产生了 <code>fiber</code> 之后，再次渲染的 <code>vdom</code> 要和之前的 <code>fiber</code> 对比下，再决定如何产生新的 <code>fiber</code>，目标是尽可能复用已有的 <code>fiber</code> 节点，这叫做 <code>diff 算法</code>。</p>
<h2 id="所以-React-的-diff-算法是分成两次遍历的："><a href="#所以-React-的-diff-算法是分成两次遍历的：" class="headerlink" title="所以 React 的 diff 算法是分成两次遍历的："></a>所以 React 的 diff 算法是分成两次遍历的：</h2><ul>
<li><p>第一轮遍历，一一对比 <code>vdom</code> 和老的 <code>fiber</code>，如果可以复用就处理下一个节点，否则就结束遍历。</p>
<ul>
<li><p>如果所有的新的 <code>vdom</code> 处理完了，那就把剩下的老 <code>fiber</code> 节点删掉就行。</p>
</li>
<li><p>如果还有 <code>vdom</code> 没处理，那就进行第二次遍历：</p>
</li>
</ul>
</li>
<li><p>第二轮遍历，把剩下的老 <code>fiber</code> 放到 <code>map</code> 里，遍历剩下的 <code>vdom</code>，从 <code>map</code> 里查找，如果找到了，就移动过来。 </p>
<ul>
<li><p>第二轮遍历完了之后，把剩余的老 <code>fiber</code> 删掉，剩余的 <code>vdom</code> 新增。</p>
</li>
<li><p>这样就完成了新的 <code>fiber</code> 结构的创建，也就是 <code>reconcile</code> 的过程。</p>
</li>
</ul>
</li>
</ul>
<h1 id="HOC"><a href="#HOC" class="headerlink" title="HOC"></a>HOC</h1><blockquote>
<p>以组件做为入参并且返回一个新的组件</p>
</blockquote>
<h2 id="使用原因："><a href="#使用原因：" class="headerlink" title="使用原因："></a>使用原因：</h2><ol>
<li>抽离重复代码，实现组件复用</li>
<li>条件渲染渲染拦截</li>
<li>拦截组件的生命周期</li>
</ol>
<h2 id="使用场景："><a href="#使用场景：" class="headerlink" title="使用场景："></a>使用场景：</h2><ol>
<li>属性代理 （模拟修改/操作传入的值）<br>props<br>state  </li>
</ol>
<ol start="2">
<li><p>条件渲染，外部逻辑的封装</p>
</li>
<li><p>反向继承(组件复制类组件)</p>
</li>
<li><p>生命周期的拦截(通过原型链获取生命周期 并绑定this指向)</p>
</li>
</ol>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
    </footer>
  </div>

    
 
   
</article>

    
    <article
  id="post-reactQ&amp;A"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2023/04/08/reactQ&A/"
    >Q&amp;A</a> 
</h2>
 

    </header>
     
    <div class="article-meta">
      <a href="/2023/04/08/reactQ&A/" class="article-date">
  <time datetime="2023-04-08T04:21:42.000Z" itemprop="datePublished">2023-04-08</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/react/">react</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <blockquote>
<p>答案源于chatgpt</p>
</blockquote>
<h2 id="React-的特点和优势是什么？"><a href="#React-的特点和优势是什么？" class="headerlink" title="React 的特点和优势是什么？"></a>React 的特点和优势是什么？</h2><ol>
<li><p><strong>声明式编程</strong><br>React 使用声明式编程，可以让开发者更加专注于组件的数据和状态，而不用关心底层的 DOM 操作。</p>
</li>
<li><p><strong>组件化开发</strong><br>React 采用组件化开发的方式，可以将 UI 拆分成多个小的、独立的组件，从而提高代码的可复用性、可测试性和可维护性。</p>
</li>
<li><p><strong>虚拟 DOM</strong><br>React 使用虚拟 DOM，可以避免不必要的 DOM 操作，从而提高性能。虚拟 DOM 是一个轻量级的 JavaScript 对象，它代表了真实 DOM 的结构和状态，React 可以通过比较两个虚拟 DOM 的差异，最小化 DOM 操作的次数。</p>
</li>
<li><p><strong>单向数据流</strong><br>React 使用单向数据流，数据从父组件传递到子组件，子组件通过 props 属性接收数据，并且不能直接修改父组件的数据。这种数据流的方式可以使组件更加可预测、可控，从而提高代码的可读性和可维护性。</p>
</li>
<li><p><strong>高效的渲染</strong><br>React 使用高效的算法来确定组件的更新，可以最小化 DOM 操作的次数，从而提高性能。React 还提供了一些性能优化的技术，如 shouldComponentUpdate、PureComponent、memo 等。</p>
</li>
<li><p><strong>社区和生态系统</strong><br>React 拥有庞大的社区和生态系统，有大量的第三方库和插件可供使用，可以帮助开发者更快地完成项目开发。</p>
</li>
</ol>
<h2 id="什么是-Virtual-DOM？它的作用是什么？"><a href="#什么是-Virtual-DOM？它的作用是什么？" class="headerlink" title="什么是 Virtual DOM？它的作用是什么？"></a>什么是 Virtual DOM？它的作用是什么？</h2><blockquote>
<p>把DOM结构转化成JavaScript对象来进行对比、减少DOM的更新</p>
</blockquote>
<p>Virtual DOM（虚拟DOM）是 React 的核心概念之一，它是一个轻量级的 JavaScript 对象，代表了真实 DOM 的结构和状态。Virtual DOM 的作用是减少 DOM 操作的次数，从而提高性能。<br>在 React 中，当组件的状态发生变化时，React 会重新构建 Virtual DOM 树，并且通过对比前后两个 Virtual DOM 树的差异，最小化 DOM 操作的次数。这种方式可以避免不必要的 DOM 操作，从而提高性能。<br>具体地，React 会将 Virtual DOM 树映射到真实的 DOM 树上，通过 DOM Diff 算法找出需要更新的节点，并且只更新这些节点的内容。由于 Virtual DOM 是一个轻量级的 JavaScript 对象，它的更新速度非常快，因此可以大大提高性能。<br>另外，Virtual DOM 还可以让开发者更加专注于组件的数据和状态，而不用关心底层的 DOM 操作。这种方式可以使组件更加易于维护和测试，从而提高代码的质量和可读性。<br>总之，Virtual DOM 是 React 的核心技术之一，它的作用是减少 DOM 操作的次数，提高性能，并且提高代码的可维护性和可读性</p>
<h2 id="什么是-JSX？它有什么优点？"><a href="#什么是-JSX？它有什么优点？" class="headerlink" title="什么是 JSX？它有什么优点？"></a>什么是 JSX？它有什么优点？</h2><blockquote>
<p>JSX 是一种 <code>JavaScript</code> 的<code>语法扩展</code>，它可以在 <code>JavaScript</code> 中编写类似于 <code>HTML</code> 的代码。在 React 中，开发者使用 JSX 来描述 UI 组件的结构和样式。</p>
</blockquote>
<h3 id="JSX-的优点如下："><a href="#JSX-的优点如下：" class="headerlink" title="JSX 的优点如下："></a>JSX 的优点如下：</h3><ol>
<li><p><strong>提高代码的可读性</strong><br>使用 JSX 可以将组件的结构和样式直接写在 JavaScript 中，从而提高代码的可读性和可维护性。</p>
</li>
<li><p><strong>提供了静态类型检查</strong><br>JSX 可以与 TypeScript 或 Flow 等静态类型检查工具一起使用，可以在编译时检查代码的类型错误，从而提高代码的<code>可靠性</code>。</p>
</li>
<li><p><strong>更加灵活</strong><br>JSX 可以使用 JavaScript 的所有特性，包括变量、函数、循环等，从而使组件更加灵活。</p>
</li>
<li><p><strong>提供了高效的渲染方式</strong><br>React 使用 Virtual DOM 来更新组件的 UI，而 JSX 可以直接转换成 JavaScript 对象，从而提高渲染的效率。</p>
</li>
<li><p><strong>容易上手</strong><br>对于熟悉 HTML 和 JavaScript 的开发者来说，使用 JSX 可以使学习 React 更加容易上手。<br>总之，JSX 是 React 的核心概念之一，它可以提高代码的可读性、可维护性和可靠性，同时也提供了高效的渲染方式和更加灵活的组件编写方式。</p>
</li>
</ol>
<h2 id="React-中的状态和属性有什么区别？它们如何传递？"><a href="#React-中的状态和属性有什么区别？它们如何传递？" class="headerlink" title="React 中的状态和属性有什么区别？它们如何传递？"></a>React 中的状态和属性有什么区别？它们如何传递？</h2><h3 id="React-中状态和属性的区别："><a href="#React-中状态和属性的区别：" class="headerlink" title="React 中状态和属性的区别："></a>React 中状态和属性的区别：</h3><ul>
<li>状态 (<code>state</code>) 是组件<code>内部自己管理的数据</code>，<code>可以</code>在组件内部进行<code>修改和更新</code>。状态通常是通过 <code>this.state</code> 来访问和修改。  </li>
<li>属性 (<code>props</code>) 是组件<code>外部传入的数据</code>，一旦传入就<code>不可以</code>被组件自己<code>修改和更新</code>。属性通常是通过组件的参数来传入。</li>
</ul>
<h3 id="如何传递状态和属性："><a href="#如何传递状态和属性：" class="headerlink" title="如何传递状态和属性："></a>如何传递状态和属性：</h3><h4 id="传递属性"><a href="#传递属性" class="headerlink" title="传递属性"></a>传递属性</h4><p>通过组件属性传递数据，父组件可以将数据通过属性传递给子组件，子组件通过 <code>this.props</code> 获取传递过来的数据。</p>
<h4 id="传递状态"><a href="#传递状态" class="headerlink" title="传递状态"></a>传递状态</h4><p>在组件中定义状态，可以通过 <code>this.state</code> 来访问和修改状态。当状态发生变化时，React 会重新渲染组件。<br>父组件也可以通过属性的方式向子组件传递回调函数，子组件在合适的时候调用这个回调函数，将状态更新的请求传递给父组件，父组件再通过属性将新的状态传递给子组件，从而达到数据传递的目的。<br>需要注意的是，状态的修改必须通过 <code>setState</code> 方法进行，而不能直接修改状态，否则可能会出现一些不可预测的问题。</p>
<h2 id="React-中如何实现组件的复用？"><a href="#React-中如何实现组件的复用？" class="headerlink" title="React 中如何实现组件的复用？"></a>React 中如何实现组件的复用？</h2><ol>
<li><p><strong>组合</strong><br>React 组件可以通过组合方式实现复用。组件可以包含其他组件，从而实现更复杂的 UI。通过组件的 props 属性，可以将数据和函数传递到组件中，从而实现更灵活的组合方式。</p>
</li>
<li><p><strong>继承</strong><br>React 组件也可以通过继承方式实现复用。通过继承 React.Component 类，可以实现代码的复用。子类继承父类的功能，可以通过<code>覆盖父类的方法</code>来实现特定的功能。</p>
</li>
<li><p><strong>高阶组件</strong><br>高阶组件是一种模式，通过将一个<code>组件作为参数传递到一个函数中，返回一个新的组件</code>，从而实现组件的复用。高阶组件可以封装一些通用的逻辑，从而让组件更加简洁。</p>
</li>
<li><p><strong>Render Props</strong><br>Render Props 是一种模式，通过将一个组件的 render 方法作为参数传递到一个函数中，返回一个新的组件，从而实现组件的复用。Render Props 可以让组件更加灵活，从而适应不同的场景。</p>
</li>
<li><p><strong>Hook</strong><br>Hook 是 React 16.8 引入的新特性，可以让函数组件具有类组件的一些功能，从而实现组件的复用。Hook 可以让组件更加简洁，从而提高代码的可读性和可维护性。</p>
</li>
</ol>
<h2 id="React-中的生命周期有哪些？它们的作用是什么？"><a href="#React-中的生命周期有哪些？它们的作用是什么？" class="headerlink" title="React 中的生命周期有哪些？它们的作用是什么？"></a>React 中的生命周期有哪些？它们的作用是什么？</h2><p>React 中的生命周期可以分为三个阶段：挂载阶段、更新阶段和卸载阶段。每个阶段都有对应的生命周期方法，它们的作用如下：</p>
<ol>
<li>挂载阶段<br>在挂载阶段，组件将被插入到 DOM 树中。React 中的挂载阶段有如下生命周期方法：</li>
</ol>
<ul>
<li><p><code>constructor</code>: 组件的构造函数，在组件被创建时调用，用于<code>初始化</code>状态和绑定方法。</p>
</li>
<li><p><code>getDerivedStateFromProps</code>: 在组件被挂载之前调用，用于根据新的属性值和状态值计算出新的状态值。</p>
</li>
<li><p><code>componentWillMount</code>: DOM挂在之前执行</p>
</li>
<li><p><code>render</code>: 返回组件的 UI 结构，必须被实现。</p>
</li>
<li><p><code>componentDidMount</code>: 在组件被挂载后调用，用于执行一些副作用操作，如数据请求、DOM 操作等。</p>
</li>
</ul>
<ol>
<li>更新阶段<br>在更新阶段，组件的状态或属性发生了变化，需要更新组件的 UI。React 中的更新阶段有如下生命周期方法：</li>
</ol>
<ul>
<li><p><code>getDerivedStateFromProps</code>: 在更新阶段也会被调用，用于根据新的属性值和状态值计算出新的状态值。</p>
</li>
<li><p><code>shouldComponentUpdate</code>: 在组件更新之前调用，用于判断是否需要更新组件，可以优化组件的性能。</p>
</li>
<li><p><code>render</code>: 返回组件的 UI 结构，必须被实现。</p>
</li>
<li><p><code>getSnapshotBeforeUpdate</code>: 在组件更新之前调用，用于返回一个快照，在 componentDidUpdate 中使用。</p>
</li>
<li><p><code>componentDidUpdate</code>: 在组件更新之后调用，用于执行一些副作用操作，如数据请求、DOM 操作等。</p>
</li>
</ul>
<ol start="3">
<li>卸载阶段<br>在卸载阶段，组件将被从 DOM 树中移除。React 中的卸载阶段有如下生命周期方法：</li>
</ol>
<ul>
<li><code>componentWillUnmount</code>: 在组件被卸载之前调用，用于清理一些副作用操作，如定时器、事件监听器等。<br>总之，React 的生命周期方法可以让开发者在组件的不同阶段执行一些操作，如初始化状态、执行副作用操作、清理资源等。开发者可以根据需要重写这些生命周期方法，以实现自己的业务逻辑。</li>
</ul>
<h2 id="什么是-React-Hooks？它们的作用是什么？如何使用？"><a href="#什么是-React-Hooks？它们的作用是什么？如何使用？" class="headerlink" title="什么是 React Hooks？它们的作用是什么？如何使用？"></a>什么是 React Hooks？它们的作用是什么？如何使用？</h2><p>它们是一些特殊的函数，可以让<code>函数组件具有类组件的一些功能</code>。React Hooks 的作用是为了让开发者更方便地在函数组件中使用 React 的特性，从而提高代码的可读性和可维护性。<br>React Hooks 目前提供了以下几个常用的 Hook：</p>
<ol>
<li><p><strong>useState：</strong> 用于在函数组件中使用<code>状态</code>。</p>
</li>
<li><p><strong>useEffect：</strong> 用于在函数组件中使用<code>副作用</code>（如数据获取、DOM 操作等）。</p>
</li>
<li><p><strong>useContext：</strong> 用于在函数组件中<code>使用上下文</code>。</p>
</li>
<li><p><strong>useReducer：</strong> 用于在函数组件中使用 Reducer。</p>
</li>
<li><p><strong>useCallback：</strong> 用于在函数组件中<code>缓存回调函数</code>。</p>
</li>
<li><p><strong>useMemo：</strong> 用于在函数组件中<code>缓存计算结果</code>。</p>
</li>
</ol>
<h3 id="使用-React-Hooks-的步骤如下："><a href="#使用-React-Hooks-的步骤如下：" class="headerlink" title="使用 React Hooks 的步骤如下："></a>使用 React Hooks 的步骤如下：</h3><ol>
<li><p>在函数组件中导入所需的 Hook。</p>
</li>
<li><p>在函数组件中声明 Hook。</p>
</li>
<li><p>在 Hook 中使用 React 的特性。</p>
</li>
<li><p>将 Hook 返回的值用于组件的渲染。</p>
</li>
</ol>
<h2 id="Redux-是什么？它的作用是什么？如何使用？"><a href="#Redux-是什么？它的作用是什么？如何使用？" class="headerlink" title="Redux 是什么？它的作用是什么？如何使用？"></a>Redux 是什么？它的作用是什么？如何使用？</h2><blockquote>
<p>Redux 是一个用于<code>管理应用程序状态</code>的 JavaScript 库。它可以在应用程序中创建一个全局的状态存储器，使得不同的组件可以轻松地共享和访问应用程序状态。</p>
</blockquote>
<h3 id="Redux-的作用包括以下几个方面："><a href="#Redux-的作用包括以下几个方面：" class="headerlink" title="Redux 的作用包括以下几个方面："></a>Redux 的作用包括以下几个方面：</h3><ol>
<li><p><strong>状态集中管理：</strong> Redux 将应用程序状态集中管理，使得开发者可以更加方便地管理应用程序状态，避免了状态分散的问题。</p>
</li>
<li><p><strong>数据流的清晰可控：</strong> Redux 采用了单向数据流的模式，使得数据的流动清晰可控，便于调试和维护。</p>
</li>
<li><p><strong>方便进行状态管理：</strong> Redux 提供了一些方便进行状态管理的工具，如中间件、调试工具等。</p>
</li>
</ol>
<h3 id="使用-Redux-可以分为以下几个步骤："><a href="#使用-Redux-可以分为以下几个步骤：" class="headerlink" title="使用 Redux 可以分为以下几个步骤："></a>使用 Redux 可以分为以下几个步骤：</h3><ol>
<li><p><strong>安装 Redux 库：</strong> 在项目中安装 Redux 库，可以使用 npm 或 yarn 进行安装。</p>
</li>
<li><p><strong>创建 Store：</strong> 在应用程序中创建一个全局的 Store，Store 中保存了应用程序的状态。</p>
</li>
<li><p><strong>创建 Reducer：</strong> Reducer 是一个纯函数，用于描述应用程序状态的变化。Reducer 接收当前的状态和一个 action 作为参数，并返回一个新的状态。</p>
</li>
<li><p><strong>创建 Action：</strong> Action 是一个 JavaScript 对象，用于描述状态的变化。Action 中必须包含一个 type 属性，用于标识这个 Action 的类型。</p>
</li>
<li><p><strong>创建 Dispatch：</strong> Dispatch 是一个函数，用于将 Action 发送到 Reducer 中，从而更新应用程序的状态。</p>
</li>
<li><p><strong>创建 Subscriber：</strong> Subscriber 是一个函数，用于监听 Store 中状态的变化。当状态发生变化时，Subscriber 会被自动调用。</p>
</li>
</ol>
<p>总之，Redux 提供了一种方便、清晰、可控的状态管理方式，可以帮助开发者更加方便地管理应用程序状态，从而提高应用程序的可维护性和可扩展性。</p>
<h2 id="React-Router-是什么？它的作用是什么？如何使用？"><a href="#React-Router-是什么？它的作用是什么？如何使用？" class="headerlink" title="React Router 是什么？它的作用是什么？如何使用？"></a>React Router 是什么？它的作用是什么？如何使用？</h2><blockquote>
<p>React Router 是一个用于 React 应用程序中进行<code>路由管理</code>的库。它可以帮助开发者更加方便地管理应用程序的路由，实现页面的跳转和传递参数等功能。</p>
</blockquote>
<h3 id="React-Router-的作用包括以下几个方面："><a href="#React-Router-的作用包括以下几个方面：" class="headerlink" title="React Router 的作用包括以下几个方面："></a>React Router 的作用包括以下几个方面：</h3><ol>
<li><p><strong>实现路由功能：</strong> React Router 可以帮助开发者将应用程序的不同页面进行路由管理，实现页面跳转和参数传递等功能。</p>
</li>
<li><p><strong>支持嵌套路由：</strong> React Router 支持嵌套路由，可以在不同的路由之间进行跳转。</p>
</li>
<li><p><strong>方便进行路由拦截和重定向：</strong> React Router 提供了方便进行路由拦截和重定向的功能。</p>
</li>
</ol>
<h3 id="使用-React-Router-可以分为以下几个步骤："><a href="#使用-React-Router-可以分为以下几个步骤：" class="headerlink" title="使用 React Router 可以分为以下几个步骤："></a>使用 React Router 可以分为以下几个步骤：</h3><ol>
<li><p>安装 React Router 库：在项目中安装 React Router 库，可以使用 npm 或 yarn 进行安装。</p>
</li>
<li><p>创建路由组件：在应用程序中创建路由组件，可以使用 BrowserRouter 或 HashRouter 等组件包裹应用程序的根组件，实现路由的管理。</p>
</li>
<li><p>配置路由规则：在路由组件中配置路由规则，可以使用 Route 组件来匹配不同的路由规则，并指定对应的组件。</p>
</li>
<li><p>实现页面跳转：在应用程序中使用 Link 或 NavLink 组件实现页面的跳转。</p>
</li>
<li><p>传递参数：在路由规则中可以使用参数来匹配不同的路由，也可以使用 location 对象来传递参数。</p>
</li>
</ol>
<p>总之，React Router 提供了一种方便、灵活、可扩展的路由管理方式，可以帮助开发者更加方便地管理应用程序的路由，从而提高应用程序的可维护性和可扩展性。</p>
<h2 id="React-中如何进行性能优化？"><a href="#React-中如何进行性能优化？" class="headerlink" title="React 中如何进行性能优化？"></a>React 中如何进行性能优化？</h2><ol>
<li><p>使用 <code>shouldComponentUpdate</code> 避免不必要的渲染。<code>shouldComponentUpdate</code> 是 React 生命周期中的一个方法，在组件更新前被调用，可以通过返回 false 避免组件的不必要渲染。</p>
</li>
<li><p>使用 <code>PureComponent</code> 和 <code>memo</code> 减少不必要的渲染。PureComponent 和 memo 都是 React 提供的函数，可以用来优化组件的渲染，避免不必要的更新。</p>
</li>
<li><p>使用 <code>key</code> 属性优化列表渲染。在渲染列表时，为每个列表项添加一个唯一的 key 属性，可以帮助 React 更好地识别哪些列表项需要更新，从而提高性能。</p>
</li>
<li><p>懒加载和代码分割。通过按需加载组件和模块，可以减少初始加载时需要下载的代码量，提高页面加载速度。</p>
</li>
<li><p>使用 <code>React.memo</code> 包装组件，缓存组件。当组件的输入参数没有发生变化时，memo 可以帮助 React 缓存组件的输出结果，避免不必要的重新渲染。</p>
</li>
<li><p>使用 React DevTools 分析性能。React DevTools 是一个浏览器插件，可以帮助开发者分析组件的渲染性能，找到渲染性能瓶颈并进行优化。</p>
</li>
<li><p>以上是 React 中常用的性能优化技术，当然还有其他的一些技术，如使用 <code>CDN</code> 加速静态资源加载、使用 <code>Webpack</code> 进行代码分割和懒加载等。开发者可以根据具体的场景选择适合的优化技术。</p>
</li>
</ol>
<h2 id="vue和react的区别，各自的优劣"><a href="#vue和react的区别，各自的优劣" class="headerlink" title="vue和react的区别，各自的优劣"></a>vue和react的区别，各自的优劣</h2><ol>
<li><p>数据绑定方式不同：<br><code>Vue</code> 的数据绑定采用<code>双向绑定</code>，可以自动将数据的变化同步到视图中，也可以将视图事件的变化同步到数据中。<br><code>React</code> 的数据绑定采用<code>单向绑定</code>，只能将数据的变化同步到视图中，无法将视图事件的变化直接同步到数据中。</p>
</li>
<li><p>组件通信方式不同：<br><code>Vue</code> 的组件通信方式包括 <code>props</code> 和<code>事件</code>，父组件通过 props 向子组件传递数据，子组件通过 <code>$emit</code> 触发事件向父组件传递数据。<br><code>React</code> 的组件通信方式采用 <code>props</code> 和<code>回调函数</code>，父组件通过 props 向子组件传递数据和回调函数，子组件通过回调函数向父组件传递数据。  </p>
</li>
<li><p>模板语法不同：<br><code>Vue</code> 的模板语法(<code>&lt;template&gt;</code>)更加简洁易懂，可以直接在模板中使用变量和表达式。而 React 的模板语法采用 <code>JSX</code> 语法，需要在 <code>JavaScript 代码中嵌入 HTML 标签和属性</code>。</p>
</li>
<li><p>学习成本不同：<br><code>Vue</code> 的学习成本相对较低，因为它的 <code>API</code> 设计更加<code>简单易用</code>，不需要太多的编程经验就可以<code>快速上手</code>。<br><code>React</code> 的学习成本相对较高，因为它的 <code>API</code> 设计更加<code>灵活</code>，需要更多的编程经验才能熟练使用。</p>
</li>
<li><p>性能表现不同：<br>Vue 的性能表现相对较好，因为它采用了虚拟 DOM 技术，可以降低 DOM 操作的频率和复杂度。而 React 的性能表现也相对较好，因为它采用了状态管理和组件化等技术，可以提高代码的可维护性和可复用性。</p>
</li>
</ol>
<p>总之，Vue 和 React 都具有各自的优点和缺点，开发者可以根据自己的需求选择适合自己的框架。<br>如果需要<code>快速开发简单应用</code>，建议使用 <code>Vue</code>；如果需要开发<code>大型应用或需要更高的灵活性和可扩展性</code>，建议使用 <code>React</code>。</p>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
    </footer>
  </div>

    
 
   
</article>

    
    <article
  id="post-ECharts"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2022/10/14/ECharts/"
    >ECharts</a> 
</h2>
 

    </header>
     
    <div class="article-meta">
      <a href="/2022/10/14/ECharts/" class="article-date">
  <time datetime="2022-10-14T02:21:42.000Z" itemprop="datePublished">2022-10-14</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/echarts/">echarts</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <h1 id="ECharts"><a href="#ECharts" class="headerlink" title="ECharts"></a>ECharts</h1><h2 id="常用配置"><a href="#常用配置" class="headerlink" title="常用配置"></a>常用配置</h2><h2 id="tooltip-提示框"><a href="#tooltip-提示框" class="headerlink" title="tooltip 提示框"></a><a target="_blank" rel="noopener" href="https://echarts.apache.org/zh/option.html#tooltip">tooltip 提示框</a></h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">   tooltip:&#123;</span><br><span class="line">    show: <span class="literal">true</span> | <span class="literal">false</span>,</span><br><span class="line">    trigger: <span class="string">&#x27;item&#x27;</span> | <span class="string">&#x27;axis&#x27;</span> | <span class="string">&#x27;none&#x27;</span>,  <span class="comment">// 触发类型</span></span><br><span class="line">    formatter: <span class="string">&#x27;&#x27;</span> | <span class="function">(<span class="params">&#123;marker,name,percent,&#125;</span>)=&gt;</span><span class="string">&#x27;&#x27;</span>,  <span class="comment">// 浮层自定义内容 marker图标 percent占比 name名称</span></span><br><span class="line">   &#125; </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">params = &#123;</span><br><span class="line">    componentType: <span class="string">&#x27;series&#x27;</span>,</span><br><span class="line">    <span class="comment">// 系列类型</span></span><br><span class="line">    seriesType: string,</span><br><span class="line">    <span class="comment">// 系列在传入的 option.series 中的 index</span></span><br><span class="line">    seriesIndex: number,</span><br><span class="line">    <span class="comment">// 系列名称</span></span><br><span class="line">    seriesName: string,</span><br><span class="line">    <span class="comment">// 数据名，类目名</span></span><br><span class="line">    name: string,</span><br><span class="line">    <span class="comment">// 数据在传入的 data 数组中的 index</span></span><br><span class="line">    dataIndex: number,</span><br><span class="line">    <span class="comment">// 传入的原始数据项</span></span><br><span class="line">    data: <span class="built_in">Object</span>,</span><br><span class="line">    <span class="comment">// 传入的数据值。在多数系列下它和 data 相同。在一些系列下是 data 中的分量（如 map、radar 中）</span></span><br><span class="line">    value: number|<span class="built_in">Array</span>|<span class="built_in">Object</span>,</span><br><span class="line">    <span class="comment">// 坐标轴 encode 映射信息，</span></span><br><span class="line">    <span class="comment">// key 为坐标轴（如 &#x27;x&#x27; &#x27;y&#x27; &#x27;radius&#x27; &#x27;angle&#x27; 等）</span></span><br><span class="line">    <span class="comment">// value 必然为数组，不会为 null/undefied，表示 dimension index 。</span></span><br><span class="line">    <span class="comment">// 其内容如：</span></span><br><span class="line">    <span class="comment">// &#123;</span></span><br><span class="line">    <span class="comment">//     x: [2] // dimension index 为 2 的数据映射到 x 轴</span></span><br><span class="line">    <span class="comment">//     y: [0] // dimension index 为 0 的数据映射到 y 轴</span></span><br><span class="line">    <span class="comment">// &#125;</span></span><br><span class="line">    encode: <span class="built_in">Object</span>,</span><br><span class="line">    <span class="comment">// 维度名列表</span></span><br><span class="line">    dimensionNames: <span class="built_in">Array</span>&lt;<span class="built_in">String</span>&gt;,</span><br><span class="line">    <span class="comment">// 数据的维度 index，如 0 或 1 或 2 ...</span></span><br><span class="line">    <span class="comment">// 仅在雷达图中使用。</span></span><br><span class="line">    dimensionIndex: number,</span><br><span class="line">    <span class="comment">// 数据图形的颜色</span></span><br><span class="line">    color: string,</span><br><span class="line">    <span class="comment">// 饼图，漏斗图的百分比</span></span><br><span class="line">    percent: number</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="legend-图例组件"><a href="#legend-图例组件" class="headerlink" title="legend 图例组件"></a><a target="_blank" rel="noopener" href="https://echarts.apache.org/zh/option.html#legend">legend 图例组件</a></h2><ul>
<li><code>series</code>内的数据对象必须要有 <code>name</code> 属性</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line"> legend:&#123;</span><br><span class="line">    ...</span><br><span class="line">    itemStyle:&#123;&#125;, <span class="comment">// 图例‘图形’的样式</span></span><br><span class="line">    lineStyle:&#123;&#125;, <span class="comment">// 图例‘线’的样式</span></span><br><span class="line">    formatter: <span class="string">&#x27;&#123;name&#125;&#x27;</span> | <span class="function">(<span class="params">name</span>)=&gt;</span><span class="string">&#x27;&#x27;</span>,  <span class="comment">// 图例自定义内容</span></span><br><span class="line">    icon: <span class="string">&#x27;circle&#x27;</span> | <span class="string">&#x27;rect&#x27;</span> | <span class="string">&#x27;roundRect&#x27;</span> | <span class="string">&#x27;triangle&#x27;</span> | <span class="string">&#x27;diamond&#x27;</span> | <span class="string">&#x27;pin&#x27;</span> | <span class="string">&#x27;arrow&#x27;</span> | <span class="string">&#x27;none&#x27;</span> <span class="comment">// 图例项的icon</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">//  针对多个series进行个性化设置</span></span><br><span class="line">    data: [</span><br><span class="line">      &#123;</span><br><span class="line">         name:<span class="string">&#x27;a&#x27;</span>,</span><br><span class="line">         ...</span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">         name:<span class="string">&#x27;b&#x27;</span>,</span><br><span class="line">         ...</span><br><span class="line">      &#125;</span><br><span class="line">    ]</span><br><span class="line"> &#125;,</span><br><span class="line"> series:[</span><br><span class="line">    &#123;</span><br><span class="line">        name:<span class="string">&#x27;a&#x27;</span>,</span><br><span class="line">        ...</span><br><span class="line">    &#125;</span><br><span class="line"> ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="grid-坐标系网格"><a href="#grid-坐标系网格" class="headerlink" title="grid 坐标系网格"></a><a target="_blank" rel="noopener" href="https://echarts.apache.org/zh/option.html#grid">grid 坐标系网格</a></h2><blockquote>
<p>文字过长 通过left/bottom的距离设置  eg：<code>16 + fontSize * maxYLabelLength * 1.2,</code></p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">   grid:&#123;</span><br><span class="line">      <span class="comment">// 距离容器 上下左右的距离</span></span><br><span class="line">      left(right/top/bottom): <span class="number">20</span> (具体像素) | <span class="string">&#x27;20%&#x27;</span>(百分比) |　<span class="string">&#x27;left&#x27;</span>|<span class="string">&#x27;center&#x27;</span>|<span class="string">&#x27;middle&#x27;</span>|<span class="string">&#x27;right&#x27;</span>|<span class="string">&#x27;bottom&#x27;</span>|<span class="string">&#x27;top&#x27;</span>,</span><br><span class="line"></span><br><span class="line">      <span class="comment">// grid组件的宽高</span></span><br><span class="line">      width(height): string | number | <span class="string">&#x27;auto&#x27;</span></span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="yAxis-y轴"><a href="#yAxis-y轴" class="headerlink" title="yAxis y轴"></a><a target="_blank" rel="noopener" href="https://echarts.apache.org/zh/option.html#yAxis">yAxis y轴</a></h2><ul>
<li>多个<code>y</code>轴的情况用数组,<code>name</code>对应<code>series</code>的<code>name</code></li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">   yAxis:[</span><br><span class="line">      &#123;</span><br><span class="line">         name:<span class="string">&#x27;a&#x27;</span>,</span><br><span class="line">         nameLocation:<span class="string">&#x27;center&#x27;</span> | <span class="string">&#x27;start&#x27;</span> | <span class="string">&#x27;end&#x27;</span>, <span class="comment">// 坐标轴名称显示位置</span></span><br><span class="line">         nameGap:number, <span class="comment">// 坐标轴名称与轴线的距离</span></span><br><span class="line">         nameRotate:number, <span class="comment">// 名称的旋转角度</span></span><br><span class="line"></span><br><span class="line">         type:<span class="string">&#x27;value&#x27;</span> | <span class="string">&#x27;time&#x27;</span> | <span class="string">&#x27;category&#x27;</span> | <span class="string">&#x27;log&#x27;</span>, <span class="comment">// 数值轴、时间轴、类目轴、对数轴</span></span><br><span class="line">         min: number | string | <span class="function">(<span class="params">value</span>)=&gt;</span>number, <span class="comment">// 坐标刻度最小值</span></span><br><span class="line">         max: number | string | <span class="function">(<span class="params">value</span>)=&gt;</span>number, <span class="comment">// 坐标刻度最大值</span></span><br><span class="line">         minInterval: number, <span class="comment">// 最小间隔</span></span><br><span class="line">         splitNumber: number, <span class="comment">// 坐标分割段数 配合min、max使用</span></span><br><span class="line"></span><br><span class="line">         <span class="comment">// 坐标轴轴线相关</span></span><br><span class="line">         axisLine:&#123;</span><br><span class="line"></span><br><span class="line">         &#125;</span><br><span class="line">      &#125;,</span><br><span class="line">   ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="xAxis-x轴"><a href="#xAxis-x轴" class="headerlink" title="xAxis x轴"></a><a target="_blank" rel="noopener" href="https://echarts.apache.org/zh/option.html#xAxis">xAxis x轴</a></h2><ul>
<li>和y轴类似</li>
</ul>
<h2 id="dataZoom-区域缩放"><a href="#dataZoom-区域缩放" class="headerlink" title="dataZoom 区域缩放"></a><a target="_blank" rel="noopener" href="https://echarts.apache.org/zh/option.html#dataZoom">dataZoom 区域缩放</a></h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">dataZoom: [</span><br><span class="line">       &#123;</span><br><span class="line">         type: <span class="string">&#x27;inside&#x27;</span>, <span class="comment">// 内置</span></span><br><span class="line">         yAxisIndex: <span class="number">0</span>,</span><br><span class="line">         startValue: data.length,</span><br><span class="line">         endValue: data.length - <span class="number">12</span>,</span><br><span class="line">         filterMode: <span class="string">&#x27;filter&#x27;</span>, <span class="comment">// 主轴 &#x27;filter&#x27;，辅轴 &#x27;empty&#x27;</span></span><br><span class="line">         zoomOnMouseWheel: <span class="literal">false</span>,</span><br><span class="line">         moveOnMouseWheel: <span class="literal">true</span>,</span><br><span class="line">         moveOnMouseMove: <span class="literal">false</span></span><br><span class="line">       &#125;,</span><br><span class="line">       &#123;</span><br><span class="line">        type: <span class="string">&#x27;slider&#x27;</span>, <span class="comment">// 滚动条</span></span><br><span class="line">        ...</span><br><span class="line">       &#125;</span><br><span class="line">     ],</span><br></pre></td></tr></table></figure>


<iframe id="cp_embed_dyQXdmX" src="//codepen.io/曾zZ/embed/dyQXdmX?height=600]&theme-id=dark&slug-hash=dyQXdmX&default-tab=[" scrolling="no" frameborder="no" height="600]" allowTransparency="true" allowfullscreen="true" class="cp_embed_iframe" style="width: 100%; overflow: hidden;"></iframe>

<iframe id="cp_embed_PoxzoYa" src="//codepen.io/曾zZ/embed/PoxzoYa?height=600]&theme-id=dark&slug-hash=PoxzoYa&default-tab=[" scrolling="no" frameborder="no" height="600]" allowTransparency="true" allowfullscreen="true" class="cp_embed_iframe" style="width: 100%; overflow: hidden;"></iframe>

<iframe id="cp_embed_BaGyOwP" src="//codepen.io/曾zZ/embed/BaGyOwP?height=600]&theme-id=dark&slug-hash=BaGyOwP&default-tab=[" scrolling="no" frameborder="no" height="600]" allowTransparency="true" allowfullscreen="true" class="cp_embed_iframe" style="width: 100%; overflow: hidden;"></iframe> 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
    </footer>
  </div>

    
 
   
</article>

    
    <article
  id="post-procomponents"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2022/10/01/procomponents/"
    >ProComponents</a> 
</h2>
 

    </header>
     
    <div class="article-meta">
      <a href="/2022/10/01/procomponents/" class="article-date">
  <time datetime="2022-10-01T04:21:42.000Z" itemprop="datePublished">2022-10-01</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/antd/">antd</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <h2 id="ProTable"><a href="#ProTable" class="headerlink" title="ProTable"></a>ProTable</h2><h3 id="Columns配置项"><a href="#Columns配置项" class="headerlink" title="Columns配置项"></a><a target="_blank" rel="noopener" href="https://procomponents.ant.design/components/table#columns-%E5%88%97%E5%AE%9A%E4%B9%89">Columns配置项</a></h3><ul>
<li><a target="_blank" rel="noopener" href="https://procomponents.ant.design/components/schema/#valueenum">valueEnum</a></li>
<li><a target="_blank" rel="noopener" href="https://procomponents.ant.design/components/schema/#valuetype">valueType</a></li>
<li><a target="_blank" rel="noopener" href="https://procomponents.ant.design/components/field-set">ProFields</a></li>
<li><a target="_blank" rel="noopener" href="https://ant.design/components/form-cn/#Form.Item">From.Item</a><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> columns = [</span><br><span class="line">    &#123;</span><br><span class="line">        title:<span class="string">&#x27;&#x27;</span>,  <span class="comment">// 标签名称</span></span><br><span class="line">        dataIndex:<span class="string">&#x27;&#x27;</span>, <span class="comment">// 绑定字段</span></span><br><span class="line">        ellipsis: <span class="literal">true</span> | <span class="literal">false</span>,</span><br><span class="line">        valueEnum: [&#123;<span class="attr">label</span>:<span class="string">&#x27;&#x27;</span>,<span class="attr">value</span>:<span class="string">&#x27;&#x27;</span>&#125;],</span><br><span class="line">        valueType:<span class="string">&#x27;text&#x27;</span> | <span class="string">&#x27;date&#x27;</span> <span class="comment">// 值类型 ...</span></span><br><span class="line">        order: number <span class="comment">// 表单中的权重 越大越靠前</span></span><br><span class="line">        search: <span class="literal">true</span> | <span class="literal">false</span>, <span class="comment">// 搜索启用/隐藏</span></span><br><span class="line">        colSize: number, <span class="comment">// 表单占用格子数量 colSpan*span</span></span><br><span class="line">        hideInSearch: <span class="literal">true</span> | <span class="literal">false</span>,</span><br><span class="line">        hideInTable:<span class="literal">true</span> | <span class="literal">false</span>,</span><br><span class="line">        hideInForm:<span class="literal">true</span> | <span class="literal">false</span>,</span><br><span class="line">        initialValue:any, <span class="comment">// 初始值</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// table的render</span></span><br><span class="line">        renderText: <span class="function">(<span class="params">text,record,index,action</span>)=&gt;</span>string,</span><br><span class="line">        render: <span class="function">(<span class="params">text,record,index,action</span>)=&gt;</span>ReactNode|ReactNode[],</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 表单的输入组件 proFields / antd / 自定义组件</span></span><br><span class="line">        renderFormItem: <span class="function">(<span class="params">item,form</span>)=&gt;</span>RecatNode,</span><br><span class="line">        <span class="comment">// 表单配置</span></span><br><span class="line">        fieldProps: &#123;</span><br><span class="line">            precision:<span class="number">1</span> <span class="comment">// 精度 ... antd 表单组件相关配置</span></span><br><span class="line">        &#125;,</span><br><span class="line">        formItemProps: &#123;  <span class="comment">//  Form.Item 相关配置</span></span><br><span class="line">            rules:[ &#123; <span class="attr">required</span>:<span class="literal">true</span>|<span class="literal">false</span> &#125; ],</span><br><span class="line">            &#123;</span><br><span class="line">                message:<span class="string">&#x27;&#x27;</span>,</span><br><span class="line">                validator: (record,value)&#123;</span><br><span class="line">                    <span class="keyword">if</span>(value)<span class="keyword">return</span> <span class="built_in">Promise</span>.resolve()</span><br><span class="line">                    <span class="keyword">return</span> <span class="built_in">Promise</span>.reject()</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;,</span><br><span class="line">    ],</span><br><span class="line"></span><br><span class="line">    <span class="comment">/*  </span></span><br><span class="line"><span class="comment">    valueEnum :</span></span><br><span class="line"><span class="comment">        password	密码输入框</span></span><br><span class="line"><span class="comment">        money	金额输入框</span></span><br><span class="line"><span class="comment">        textarea	文本域</span></span><br><span class="line"><span class="comment">        date	日期</span></span><br><span class="line"><span class="comment">        dateTime	日期时间</span></span><br><span class="line"><span class="comment">        dateWeek	周</span></span><br><span class="line"><span class="comment">        dateMonth	月</span></span><br><span class="line"><span class="comment">        dateQuarter	季度输入</span></span><br><span class="line"><span class="comment">        dateYear	年份输入</span></span><br><span class="line"><span class="comment">        dateRange	日期区间</span></span><br><span class="line"><span class="comment">        dateTimeRange	日期时间区间</span></span><br><span class="line"><span class="comment">        time	时间</span></span><br><span class="line"><span class="comment">        timeRange	时间区间</span></span><br><span class="line"><span class="comment">        text	文本框</span></span><br><span class="line"><span class="comment">        select	下拉框</span></span><br><span class="line"><span class="comment">        treeSelect	树形下拉框</span></span><br><span class="line"><span class="comment">        checkbox	多选框</span></span><br><span class="line"><span class="comment">        rate	星级组件</span></span><br><span class="line"><span class="comment">        radio	单选框</span></span><br><span class="line"><span class="comment">        radioButton	按钮单选框</span></span><br><span class="line"><span class="comment">        progress	进度条</span></span><br><span class="line"><span class="comment">        percent	百分比组件</span></span><br><span class="line"><span class="comment">        digit	数字输入框</span></span><br><span class="line"><span class="comment">        second	秒格式化</span></span><br><span class="line"><span class="comment">        avatar	头像</span></span><br><span class="line"><span class="comment">        code	代码框</span></span><br><span class="line"><span class="comment">        switch	开关</span></span><br><span class="line"><span class="comment">        fromNow	相对于当前时间</span></span><br><span class="line"><span class="comment">        image	图片</span></span><br><span class="line"><span class="comment">        jsonCode	代码框，但是带了 json 格式化</span></span><br><span class="line"><span class="comment">        color	颜色选择器</span></span><br><span class="line"><span class="comment">        cascader 级联选择器</span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">   </span><br></pre></td></tr></table></figure></li>
</ul>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
    </footer>
  </div>

    
 
   
</article>

    
    <article
  id="post-websocket"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2022/09/12/websocket/"
    >websocket</a> 
</h2>
 

    </header>
     
    <div class="article-meta">
      <a href="/2022/09/12/websocket/" class="article-date">
  <time datetime="2022-09-12T02:00:00.000Z" itemprop="datePublished">2022-09-12</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/websocket/">websocket</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <h2 id="websocket"><a href="#websocket" class="headerlink" title="websocket"></a><a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket">websocket</a></h2><blockquote>
<p>在单个TCP连接上进行全双工通信的协议。浏览器服务器需要完成一次握手，两者之间就能创建持久性的连接，并进行双向数据传输。</p>
</blockquote>
<h2 id="websocket连接基本步骤"><a href="#websocket连接基本步骤" class="headerlink" title="websocket连接基本步骤"></a>websocket连接基本步骤</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">// 创建webscoket实例</span></span><br><span class="line"><span class="keyword">const</span> ws = <span class="keyword">new</span> WebSocket(<span class="string">&#x27;ws://8.140.175.191:5008/v1/ws&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 连接监听</span></span><br><span class="line">ws.onopen = <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;start&#x27;</span>, e)</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 向服务器推送消息</span></span><br><span class="line">    ws.send(<span class="string">&#x27;...&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 断连监听</span></span><br><span class="line">ws.onclose = <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;close&#x27;</span>, e)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 接收消息</span></span><br><span class="line">ws.onmessage = <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;message&#x27;</span>, e)</span><br><span class="line">    <span class="comment">// 对获取到的信息进行处理 ... （全局弹框之类的）</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 连接发生错误</span></span><br><span class="line">ws.onerror = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123; </span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
    </footer>
  </div>

    
 
   
</article>

    
    <article
  id="post-reactahooks"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2022/07/31/reactahooks/"
    >hooks&amp;ahooks</a> 
</h2>
 

    </header>
     
    <div class="article-meta">
      <a href="/2022/07/31/reactahooks/" class="article-date">
  <time datetime="2022-07-31T04:21:42.000Z" itemprop="datePublished">2022-07-31</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/react/">react</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <p><img src="https://i.postimg.cc/3r0gYsv4/20221010095328.jpg"></p>
<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>在不使用class的情况下使用<code>state</code>以及其他react特性<br>=&gt; 不论是有状态组件还是无状态组件都可以用<code>函数</code>来声明</p>
<h2 id="useState"><a href="#useState" class="headerlink" title="useState"></a>useState</h2><p><code>useState</code>通过在函数组件里调用它来给组件添加一些内部 <code>state</code>。<br><code>useState</code>会返回一对值：<code>当前状态</code> 和 <code>一个让你更新它的函数</code><br>你可以在事件处理函数中或其他一些地方调用这个函数。<br>（类似 this.setState，但是它不会把新的 state 和旧的 state 进行合并）<br><code>useState</code>的参数：state的初始值</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 引入 useState</span></span><br><span class="line"><span class="keyword">import</span> React,&#123;useState&#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="function"><span class="keyword">function</span> <span class="title">Test</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="comment">// 声明state变量count和更新count的方法setCount   （解构赋值）</span></span><br><span class="line">    <span class="keyword">const</span> [count,setCount] = useState(<span class="number">18</span>)   <span class="comment">// 赋给count的初始值为18</span></span><br><span class="line">    <span class="keyword">return</span>(</span><br><span class="line">        &lt;div&gt;</span><br><span class="line">            &lt;h3&gt;</span><br><span class="line">                count: &#123;count&#125;  &#123;<span class="comment">/* count的使用 */</span>&#125;</span><br><span class="line">            &lt;/h3&gt;</span><br><span class="line">             &#123;<span class="comment">/* setCount的使用 */</span>&#125;</span><br><span class="line">            &lt;button onClick=&#123;<span class="function">()=&gt;</span>&#123;setCount(count+<span class="number">1</span>)&#125;&#125;&gt;add&lt;/button&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">    )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Class 方法</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Test</span> <span class="keyword">extends</span> <span class="title">Component</span> </span>&#123;</span><br><span class="line">    <span class="keyword">constructor</span>(props) &#123;</span><br><span class="line">        <span class="built_in">super</span>(props);</span><br><span class="line">        <span class="built_in">this</span>.state = &#123; </span><br><span class="line">            count: <span class="number">0</span></span><br><span class="line">         &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    render() &#123; </span><br><span class="line">        <span class="keyword">return</span> ( </span><br><span class="line">            &lt;div&gt;</span><br><span class="line">            &lt;h3&gt;</span><br><span class="line">                count: &#123;<span class="built_in">this</span>.state.count&#125;</span><br><span class="line">            &lt;/h3&gt;</span><br><span class="line">            &lt;button onClick=&#123;<span class="function">()=&gt;</span><span class="built_in">this</span>.setState(&#123; <span class="attr">count</span>: <span class="built_in">this</span>.state.count + <span class="number">1</span> &#125;)&#125;&gt;add&lt;/button&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">         );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>声明多个state变量</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Test</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="comment">// state的值是按顺序存储调用的所以不能对他的声明进行条件判断</span></span><br><span class="line">  <span class="keyword">const</span> [age, setAge] = useState(<span class="number">42</span>);</span><br><span class="line">  <span class="keyword">const</span> [fruit, setFruit] = useState(<span class="string">&#x27;banana&#x27;</span>);</span><br><span class="line">  <span class="keyword">const</span> [todos, setTodos] = useState([&#123; <span class="attr">text</span>: <span class="string">&#x27;Learn Hooks&#x27;</span> &#125;]);</span><br><span class="line">  <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<p>有个问题，我按照官方文档给的示例代码写的时候<br>useState(..)会标红<br>报错：<br><span style='color:red'><br>React Hook “useState” is called in function “test” which is neither a React function component or a custom React Hook function<br></span><br>后面发现是函数命名的问题<br>解决方法：  </p>
<ol>
<li>函数名/组件名 首字母大写</li>
<li>驼峰命名法在前面+use也可 (useTest)</li>
</ol>
<h2 id="useEffect"><a href="#useEffect" class="headerlink" title="useEffect"></a>useEffect</h2><p><code>effect hook</code>在函数组件中执行<code>副作用</code>操作 (异步的)<br><code>副作用</code>: 用来代替生周期、是<code>componentDidMount</code>,<code>componentDidUpdate</code>,<code>componentWillUnmount</code>的组合（替代品）</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React,&#123;useState,useEffect&#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="function"><span class="keyword">function</span> <span class="title">Test</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">const</span> [count,setCount] = useState(<span class="number">18</span>)</span><br><span class="line">    <span class="keyword">const</span> [age,setAge] = useState(<span class="number">0</span>)</span><br><span class="line">    useEffect(<span class="function">()=&gt;</span>&#123;</span><br><span class="line">        <span class="built_in">document</span>.title = count</span><br><span class="line">    &#125;,[count])</span><br><span class="line">    <span class="comment">// 可接收第二个参数 只有在 count`改变时`触发更新 类似于computed</span></span><br><span class="line">    <span class="keyword">return</span>(</span><br><span class="line">        &lt;div&gt;</span><br><span class="line">            &lt;h3&gt;</span><br><span class="line">                count: &#123;count&#125;</span><br><span class="line">            &lt;/h3&gt;</span><br><span class="line">            &lt;h3&gt;</span><br><span class="line">                Age: &#123;age&#125;</span><br><span class="line">            &lt;/h3&gt;</span><br><span class="line">            &lt;button onClick=&#123;<span class="function">()=&gt;</span>&#123;setCount(count+<span class="number">1</span>)&#125;&#125;&gt;add&lt;/button&gt;</span><br><span class="line">             &lt;button onClick=&#123;<span class="function">()=&gt;</span>&#123;setAge(age+<span class="number">10</span>)&#125;&#125;&gt;add&lt;/button&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">    )</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>


<h2 id="useContext-状态管理类似于eventBus"><a href="#useContext-状态管理类似于eventBus" class="headerlink" title="useContext 状态管理类似于eventBus"></a>useContext 状态管理类似于eventBus</h2><ol>
<li>公共状态存储文件 <code>createContent.tsx</code></li>
</ol>
<figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; createContext &#125; <span class="keyword">from</span> <span class="string">&quot;react&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> myContext = createContext(<span class="literal">null</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> myContext;</span><br></pre></td></tr></table></figure>

<ol start="2">
<li>父组件</li>
</ol>
<figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; Button &#125; <span class="keyword">from</span> <span class="string">&#x27;antd&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> React, &#123; createContext, useState &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> myContext <span class="keyword">from</span> <span class="string">&#x27;./createContext&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> ChildPage <span class="keyword">from</span> <span class="string">&#x27;./components/ChildPage&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> () =&gt; &#123;</span><br><span class="line">  <span class="keyword">const</span> [count, setCount] = useState&lt;<span class="built_in">number</span>&gt;(<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> (</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">      &lt;h1&gt;父组件&lt;/h1&gt;</span><br><span class="line">      &lt;Button onClick=&#123;<span class="function">() =&gt;</span> setCount(count + <span class="number">1</span>)&#125;&gt;点击 &#123;count&#125;&lt;/Button&gt;</span><br><span class="line"></span><br><span class="line">      &lt;hr /&gt;</span><br><span class="line"></span><br><span class="line">      <span class="comment">// 提供器</span></span><br><span class="line">      &lt;myContext.Provider value=&#123;count&#125;&gt;</span><br><span class="line">        &lt;ChildPage /&gt;</span><br><span class="line">      &lt;/myContext.Provider&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">  );</span><br><span class="line">&#125;;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<ol start="3">
<li>子组件</li>
</ol>
<figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React, &#123; useContext &#125; <span class="keyword">from</span> <span class="string">&quot;react&quot;</span></span><br><span class="line"><span class="keyword">import</span> myContext <span class="keyword">from</span> <span class="string">&quot;../createContext&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> ChildPage: React.FC&lt;<span class="built_in">any</span>&gt; = <span class="function">() =&gt;</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> count = useContext(myContext) <span class="comment">// 通过useContext直接获取到context数据</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> (&lt;h1&gt;子组件：&#123;count&#125;&lt;/h1&gt;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> ChildPage</span><br></pre></td></tr></table></figure>

<h2 id="useReducer-需要逻辑处理state"><a href="#useReducer-需要逻辑处理state" class="headerlink" title="useReducer 需要逻辑处理state"></a>useReducer 需要逻辑处理state</h2><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 初始值</span></span><br><span class="line">  <span class="keyword">const</span> initialState = &#123; count: <span class="number">0</span> &#125;</span><br><span class="line"><span class="comment">// 数据操作</span></span><br><span class="line">  <span class="keyword">const</span> reducer = <span class="function">(<span class="params">state: &#123; count: <span class="built_in">number</span>; &#125;, action: &#123; <span class="keyword">type</span>: <span class="built_in">string</span>; &#125;</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">switch</span> (action.type) &#123;</span><br><span class="line">      <span class="keyword">case</span> <span class="string">&quot;add&quot;</span>: <span class="keyword">return</span> &#123; count: state.count + <span class="number">1</span> &#125;;</span><br><span class="line">      <span class="keyword">case</span> <span class="string">&quot;del&quot;</span>: <span class="keyword">return</span> &#123; count: state.count - <span class="number">1</span> &#125;;</span><br><span class="line">      <span class="keyword">default</span>: <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">Error</span>()</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 数据声明  </span></span><br><span class="line"> <span class="keyword">const</span> [state, dispatch] = useReducer(reducer, initialState)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用</span></span><br><span class="line"></span><br><span class="line">    &lt;h1&gt;Count:&#123;state.count&#125;&lt;/h1&gt;</span><br><span class="line">    &lt;Button onClick=&#123;<span class="function">() =&gt;</span> dispatch(&#123; <span class="keyword">type</span>: <span class="string">&#x27;add&#x27;</span> &#125;)&#125;&gt;reducer add&lt;/Button&gt;</span><br><span class="line">    &lt;Button onClick=&#123;<span class="function">() =&gt;</span> dispatch(&#123; <span class="keyword">type</span>: <span class="string">&#x27;del&#x27;</span> &#125;)&#125;&gt;reducer del&lt;/Button&gt;</span><br></pre></td></tr></table></figure>

<h2 id="useEffect-amp-useMemo"><a href="#useEffect-amp-useMemo" class="headerlink" title="useEffect &amp; useMemo"></a>useEffect &amp; useMemo</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> dom = useRef()</span><br><span class="line"><span class="keyword">const</span> state = useReactive(&#123; <span class="attr">num</span>: <span class="number">1</span>, <span class="attr">childInfo</span>: <span class="string">&#x27;hello&#x27;</span> &#125;)</span><br><span class="line"></span><br><span class="line">useEffect(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">  <span class="comment">// mounted 的时候执行 模板已经挂在到页面上，dom可以获取到</span></span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;render effect&#x27;</span>, dom, state.num)</span><br><span class="line">  <span class="comment">// dom -&gt; &#123; current:HTMLElement &#125;</span></span><br><span class="line">&#125;, [state.num])</span><br><span class="line"></span><br><span class="line">useMemo(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">  <span class="comment">// 相当于create 的时候执行 模板没有挂在到页面上，dom获取不到</span></span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;render memo&#x27;</span>, dom, state.num)</span><br><span class="line">  <span class="comment">// dom -&gt; &#123; current:undefined &#125;</span></span><br><span class="line">&#125;, [state.num])</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="useReactive-响应式数据，直接修改属性可以刷新视图"><a href="#useReactive-响应式数据，直接修改属性可以刷新视图" class="headerlink" title="useReactive 响应式数据，直接修改属性可以刷新视图"></a>useReactive 响应式数据，直接修改属性可以刷新视图</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> state = useReactive(initialState: Record&lt;string,any&gt;) <span class="comment">// 参数为一个对象</span></span><br></pre></td></tr></table></figure>

<h2 id="React-memo-amp-amp-useCallback"><a href="#React-memo-amp-amp-useCallback" class="headerlink" title="React.memo &amp;&amp; useCallback()"></a>React.memo &amp;&amp; useCallback()</h2><blockquote>
<p>在父组件中引用子组件，只要父组件有数据改变都会触发子组件刷新<br><code>React.memo()</code>用来控制是否触发子组件刷新</p>
</blockquote>
<h3 id="React-memo"><a href="#React-memo" class="headerlink" title="React.memo()"></a>React.memo()</h3><blockquote>
<p>接收两个参数，第一个是纯函数的组件，第二个参数用于对比props控制是否刷新<br>如果不传第二个参数的话则是对<code>props</code>进行<code>浅对比</code></p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React, &#123; useEffect &#125; <span class="keyword">from</span> <span class="string">&quot;react&quot;</span></span><br><span class="line">interface ChildProps &#123;</span><br><span class="line">    count: number</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> Child: React.FC&lt;ChildProps&gt; = <span class="function">(<span class="params">&#123;count&#125;</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;child render&#x27;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="xml"><span class="tag">&lt;&gt;</span></span></span><br><span class="line"><span class="xml">        child</span></span><br><span class="line"><span class="xml">        count: &#123;count&#125;</span></span><br><span class="line"><span class="xml">    <span class="tag">&lt;/&gt;</span></span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">isRefresh</span>(<span class="params">prevProps: ChildProps, nextProps: ChildProps</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (prevProps.count === nextProps.count) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> React.memo(Child, isRefresh)</span><br></pre></td></tr></table></figure>

<h3 id="useCallback"><a href="#useCallback" class="headerlink" title="useCallback"></a>useCallback</h3><blockquote>
<p>缓存的是函数、优化子组件防止组件的重复渲染<br>返回一个函数，只有在以来变化的时候才会更新</p>
</blockquote>
<ul>
<li>通过父组件传递给子组件的方法被调用时，会触发所有子组件更新，不管关联的值是否改变</li>
<li>如果不用<code>useCallback</code>一个输入框改变会触发两个输入框组件重新渲染</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// child.tsx</span></span><br><span class="line">interface ChildProps &#123;</span><br><span class="line">    count: number</span><br><span class="line">    onChange: any</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> Child: React.FC&lt;ChildProps&gt; = <span class="function">(<span class="params">&#123; count, onChange &#125;</span>) =&gt;</span> &#123;</span><br><span class="line"></span><br><span class="line">    useEffect(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&#x27;%c child refresh&#x27;</span>, <span class="string">&#x27;color:red&#x27;</span>)</span><br><span class="line">    &#125;)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="xml"><span class="tag">&lt;&gt;</span></span></span><br><span class="line"><span class="xml">        child</span></span><br><span class="line"><span class="xml">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">value</span>=<span class="string">&#123;count&#125;</span> <span class="attr">onChange</span>=<span class="string">&#123;onChange&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="xml">    <span class="tag">&lt;/&gt;</span></span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> React.memo(Child)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// parent.tsx</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> () =&gt; &#123;</span><br><span class="line">  <span class="keyword">let</span> [childCount, setChildCount] = useState&lt;number&gt;(<span class="number">0</span>)</span><br><span class="line">  <span class="keyword">let</span> [childCount2, setChildCount2] = useState&lt;number&gt;(<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">  useEffect(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;%c parent refresh&#x27;</span>, <span class="string">&#x27;color:blue&#x27;</span>)</span><br><span class="line">  &#125;, [])</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">  <span class="comment">// const handleChange = (e) =&gt; &#123;</span></span><br><span class="line">  <span class="comment">//   console.log(&#x27;%c change&#x27;, &#x27;color:yellow&#x27;)</span></span><br><span class="line">  <span class="comment">//   setChildCount(e.target.value)</span></span><br><span class="line">  <span class="comment">// &#125;</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// const changeChild = (e) =&gt; &#123;</span></span><br><span class="line">  <span class="comment">//   console.log(&#x27;child change&#x27;)</span></span><br><span class="line">  <span class="comment">//   setChildCount2(e.target.value)</span></span><br><span class="line">  <span class="comment">// &#125;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> handleChange = useCallback(<span class="function">(<span class="params">e</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;%c change&#x27;</span>, <span class="string">&#x27;color:yellow&#x27;</span>)</span><br><span class="line">    setChildCount(e.target.value)</span><br><span class="line">  &#125;, [])</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> changeChild = useCallback(<span class="function">(<span class="params">e</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;child change&#x27;</span>)</span><br><span class="line">    setChildCount2(e.target.value)</span><br><span class="line"></span><br><span class="line">  &#125;, [])</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> (</span><br><span class="line">    &lt;div style=&#123;&#123; <span class="attr">padding</span>: <span class="string">&#x27;50px&#x27;</span> &#125;&#125;&gt;</span><br><span class="line">      &lt;Child count=&#123;childCount&#125; onChange=&#123;handleChange&#125; /&gt;</span><br><span class="line">      &lt;br /&gt;</span><br><span class="line">      &lt;Child count=&#123;childCount2&#125; onChange=&#123;changeChild&#125; /&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">  )</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure> 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
    </footer>
  </div>

    
 
   
</article>

    
    <article
  id="post-video"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2022/07/23/video/"
    >Video标签</a> 
</h2>
 

    </header>
     
    <div class="article-meta">
      <a href="/2022/07/23/video/" class="article-date">
  <time datetime="2022-07-23T04:21:42.000Z" itemprop="datePublished">2022-07-23</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/%E8%A7%86%E9%A2%91%E7%9B%B8%E5%85%B3/">视频相关</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <h2 id="video标签相关"><a href="#video标签相关" class="headerlink" title="video标签相关"></a>video标签相关</h2><ul>
<li><a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/video">video</a></li>
<li><a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLMediaElement/controlsList">controlsList</a></li>
</ul>
<blockquote>
<p>大部分控件都能隐藏 但是<code>更多控件</code>那个控件隐藏不了 采取了自欺欺人的方法… 设置高度父元素溢出隐藏挡住</p>
</blockquote>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--controlsList  --&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">video</span></span></span><br><span class="line"><span class="tag">    <span class="attr">controlsList</span>=<span class="string">&#x27;nofullscreen nodownload noremoteplayback&#x27;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">disablePictureInPicture</span></span></span><br><span class="line"><span class="tag">    <span class="attr">className</span>=<span class="string">&quot;videoItems&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">muted</span></span></span><br><span class="line"><span class="tag">    <span class="attr">controls</span></span></span><br><span class="line"><span class="tag">    <span class="attr">width</span>=<span class="string">&quot;100%&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">height</span>=<span class="string">&quot;100%&quot;</span></span></span><br><span class="line"><span class="tag">    /&gt;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">&amp;<span class="selector-pseudo">::-webkit-media-controls-time-remaining-display</span>,</span><br><span class="line">&amp;<span class="selector-pseudo">::-webkit-media-controls-current-time-display</span>,</span><br><span class="line">&amp;<span class="selector-pseudo">::-webkit-media-controls-play-button</span>,</span><br><span class="line">&amp;<span class="selector-pseudo">::-webkit-media-controls-fullscreen-button</span>,</span><br><span class="line">&amp;<span class="selector-pseudo">::-webkit-media-controls-timeline</span>,</span><br><span class="line">&amp;<span class="selector-pseudo">::-webkit-media-controls-volume-slider</span>,</span><br><span class="line">&amp;<span class="selector-pseudo">::-webkit-media-controls-mute-button</span>,</span><br><span class="line">&amp;<span class="selector-pseudo">::-webkit-media-controls-overflow-menu-list</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: none;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&amp;<span class="selector-pseudo">::-webkit-media-controls-enclosure</span> &#123;</span><br><span class="line">  <span class="attribute">overflow</span>: hidden;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&amp;<span class="selector-pseudo">::-webkit-media-controls-panel</span> &#123;</span><br><span class="line">  <span class="attribute">height</span>: <span class="built_in">calc</span>(<span class="number">100%</span> + <span class="number">50px</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="阻止默认事件"><a href="#阻止默认事件" class="headerlink" title="阻止默认事件"></a>阻止默认事件</h2><blockquote>
<p><code>video</code>默认事件 单击播放/暂停 双击全屏</p>
</blockquote>
<blockquote>
<p>现需求是不能通过单击操作视频的播放/暂停 但是又不想去掉controls因为去掉了没有loading样式</p>
</blockquote>
<blockquote>
<p>单击默认事件阻止之后 双击的全屏事件也不能实现了QAQ , 所以双击也得自己实现</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> videoExitFullScreen = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">const</span> dom = <span class="built_in">document</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// 浏览器兼容性处理</span></span><br><span class="line">  <span class="keyword">if</span> (dom.exitFullscreen) &#123;</span><br><span class="line">    dom.exitFullscreen()</span><br><span class="line">  &#125; <span class="keyword">else</span> <span class="keyword">if</span> (dom.mozCancelFullScreen) &#123;</span><br><span class="line">    dom.mozCancelFullScreen()</span><br><span class="line">  &#125; <span class="keyword">else</span> <span class="keyword">if</span> (dom.webkitCancelFullScreen) &#123;</span><br><span class="line">    dom.webkitCancelFullScreen()</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 阻止video单击播放停止的默认事件</span></span><br><span class="line"><span class="keyword">const</span> onceClick = <span class="function">(<span class="params">event</span>) =&gt;</span> &#123;</span><br><span class="line">  event.preventDefault();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 还原video双击全屏事件</span></span><br><span class="line"><span class="keyword">const</span> singleFullScreen = <span class="function">(<span class="params">index: number</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">const</span> isFull = <span class="built_in">document</span>.fullscreenElement</span><br><span class="line">  <span class="keyword">if</span> (isFull) &#123;</span><br><span class="line">    videoExitFullScreen()</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    videoFullScreen(index)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="video播放按钮"><a href="#video播放按钮" class="headerlink" title="video播放按钮"></a>video播放按钮</h2><blockquote>
<p>因为没有加载数据源的时候<code>video</code>的播放按钮是禁用状态，而且监听不到他的点击事件</p>
</blockquote>
<h3 id="解决思路"><a href="#解决思路" class="headerlink" title="解决思路"></a>解决思路</h3><ul>
<li>通过css样式写死透明度为 1 （假装成能点的样子）</li>
<li>将一个透明的div覆盖在播放按钮的位置上</li>
<li>给div加点击事件、加载数据源，video有数据源之后就直接销毁div，原生的播放暂停按钮可以点击啦</li>
</ul>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&amp;<span class="selector-pseudo">::-webkit-media-controls-play-button</span> &#123;</span><br><span class="line">       // TODO 视频播放按钮</span><br><span class="line">       <span class="selector-tag">opacity</span>: 1;</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&lt;div className=&#123;styles[<span class="string">&quot;video-container&quot;</span>]&#125;&gt;</span><br><span class="line">  &lt;video id=<span class="string">&#x27;video&#x27;</span></span><br><span class="line">    controlsList=<span class="string">&#x27;nodownload noremoteplayback&#x27;</span></span><br><span class="line">    disablePictureInPicture</span><br><span class="line">    className=&#123;styles[<span class="string">&#x27;hide-video-control&#x27;</span>]&#125;</span><br><span class="line">    onClick=&#123;handleClick&#125;</span><br><span class="line">    controls /&gt;</span><br><span class="line">&lt;/div&gt;</span><br><span class="line"></span><br><span class="line">&#123;!flv &amp;&amp; <span class="xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&#123;styles[</span>&quot;<span class="attr">play-cover</span>&quot;]&#125; <span class="attr">onClick</span>=<span class="string">&#123;handleCoverClick&#125;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span>&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="video画中画"><a href="#video画中画" class="headerlink" title="video画中画"></a>video画中画</h2><blockquote>
<p>正常切换标签页画中画状态是可以切换回去的<br>但是路由切换的话，组件被卸载了，就回不去了<br>就需要对画中画进行禁用 给<code>video</code>加上<code>disablePictureInPicture</code>属性</p>
</blockquote>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
    </footer>
  </div>

    
 
   
</article>

    
    <article
  id="post-2022年总结"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2022/04/08/2022%E5%B9%B4%E6%80%BB%E7%BB%93/"
    >2022年度总结</a> 
</h2>
 

    </header>
     
    <div class="article-meta">
      <a href="/2022/04/08/2022%E5%B9%B4%E6%80%BB%E7%BB%93/" class="article-date">
  <time datetime="2022-04-07T17:21:42.000Z" itemprop="datePublished">2022-04-08</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/%E6%97%A5%E5%B8%B8/">日常</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <pre>
关键词：疫情

这一年上半年在前公司饱受低代码折磨后把“蓄谋已久”的离职计划付诸行动
6月初离职、6月下旬入职新公司，7月又收到别的offer，考虑后还是呆在了这家公司（虽然过后又有些后悔...
这年又是限电又是频繁封控的确实人的精神状态不是很好、戾气也很大
年底彻底开之后，没多久就阳了，这是两年多来第一次阳
有点猝不及防、物资紧缺根本买不到需要的东西
好在前同事施舍了各种防疫物资、加上症状相对较轻，算是度过了难关

经历这次疫情之后，好像想开了一点点
不知道明天会发生什么离谱的事情、不要把时间浪费在等待当中
生活不在别处、当下即是全部

23年的目标是当周末特种兵、把四川以及周边地区都走一遍！
</pre> 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
    </footer>
  </div>

    
 
   
</article>

    
  </article>
  

  
  <nav class="page-nav">
    
    <span class="page-number current">1</span><a class="page-number" href="/page/2/">2</a><a class="page-number" href="/page/3/">3</a><span class="space">&hellip;</span><a class="page-number" href="/page/7/">7</a><a class="extend next" rel="next" href="/page/2/">下一页</a>
  </nav>
  
</section>
</div>

      <footer class="footer">
  <div class="outer">
    <ul>
      <li>
        Copyrights &copy;
        2019-2023
        <i class="ri-heart-fill heart_icon"></i> John Doe
      </li>
    </ul>
    <ul>
      <li>
        
      </li>
    </ul>
    <ul>
      <li>
        
        
        <span>
  <span><i class="ri-user-3-fill"></i>Visitors:<span id="busuanzi_value_site_uv"></span></s>
  <span class="division">|</span>
  <span><i class="ri-eye-fill"></i>Views:<span id="busuanzi_value_page_pv"></span></span>
</span>
        
      </li>
    </ul>
    <ul>
      
    </ul>
    <ul>
      
    </ul>
    <ul>
      <li>
        <!-- cnzz统计 -->
        
      </li>
    </ul>
  </div>
</footer>
      <div class="float_btns">
        <div class="totop" id="totop">
  <i class="ri-arrow-up-line"></i>
</div>

<div class="todark" id="todark">
  <i class="ri-moon-line"></i>
</div>

      </div>
    </main>
    <aside class="sidebar on">
      <button class="navbar-toggle"></button>
<nav class="navbar">
  
  <div class="logo">
    <a href="/"><img src="/images/avatar.webp" alt="Doreen&#39;s Blog"></a>
  </div>
  
  <ul class="nav nav-main">
    
    <li class="nav-item">
      <a class="nav-item-link" href="/">主页</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/categories">分类</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/archives">归档</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/about">关于我</a>
    </li>
    
  </ul>
</nav>
<nav class="navbar navbar-bottom">
  <ul class="nav">
    <li class="nav-item">
      
      <a class="nav-item-link nav-item-search"  title="Search">
        <i class="ri-search-line"></i>
      </a>
      
      
    </li>
  </ul>
</nav>
<div class="search-form-wrap">
  <div class="local-search local-search-plugin">
  <input type="search" id="local-search-input" class="local-search-input" placeholder="Search...">
  <div id="local-search-result" class="local-search-result"></div>
</div>
</div>
    </aside>
    <script>
      if (window.matchMedia("(max-width: 768px)").matches) {
        document.querySelector('.content').classList.remove('on');
        document.querySelector('.sidebar').classList.remove('on');
      }
    </script>
    <div id="mask"></div>

<!-- #reward -->
<div id="reward">
  <span class="close"><i class="ri-close-line"></i></span>
  <p class="reward-p"><i class="ri-cup-line"></i>请我喝杯咖啡吧~</p>
  <div class="reward-box">
    
    <div class="reward-item">
      <img class="reward-img" src="https://cdn.jsdelivr.net/gh/Shen-Yu/cdn/img/alipay.jpg">
      <span class="reward-type">支付宝</span>
    </div>
    
    
    <div class="reward-item">
      <img class="reward-img" src="https://cdn.jsdelivr.net/gh/Shen-Yu/cdn/img/wechat.jpg">
      <span class="reward-type">微信</span>
    </div>
    
  </div>
</div>
    
<script src="/js/jquery-2.0.3.min.js"></script>


<script src="/js/lazyload.min.js"></script>

<!-- Tocbot -->

<script src="https://cdn.jsdelivr.net/npm/jquery-modal@0.9.2/jquery.modal.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-modal@0.9.2/jquery.modal.min.css">
<script src="https://cdn.jsdelivr.net/npm/justifiedGallery@3.7.0/dist/js/jquery.justifiedGallery.min.js"></script>

<script src="/dist/main.js"></script>

<!-- ImageViewer -->

<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">

    <!-- Background of PhotoSwipe. 
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>

    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">

        <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>

        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">

            <div class="pswp__top-bar">

                <!--  Controls are self-explanatory. Order can be changed. -->

                <div class="pswp__counter"></div>

                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>

                <button class="pswp__button pswp__button--share" style="display:none" title="Share"></button>

                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>

                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>

                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                        <div class="pswp__preloader__cut">
                            <div class="pswp__preloader__donut"></div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div>
            </div>

            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>

            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>

            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>

        </div>

    </div>

</div>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.min.css">
<script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js"></script>

<script>
    function viewer_init() {
        let pswpElement = document.querySelectorAll('.pswp')[0];
        let $imgArr = document.querySelectorAll(('.article-entry img:not(.reward-img)'))

        $imgArr.forEach(($em, i) => {
            $em.onclick = () => {
                // slider展开状态
                // todo: 这样不好，后面改成状态
                if (document.querySelector('.left-col.show')) return
                let items = []
                $imgArr.forEach(($em2, i2) => {
                    let img = $em2.getAttribute('data-idx', i2)
                    let src = $em2.getAttribute('data-target') || $em2.getAttribute('src')
                    let title = $em2.getAttribute('alt')
                    // 获得原图尺寸
                    const image = new Image()
                    image.src = src
                    items.push({
                        src: src,
                        w: image.width || $em2.width,
                        h: image.height || $em2.height,
                        title: title
                    })
                })
                var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, {
                    index: parseInt(i)
                });
                gallery.init()
            }
        })
    }
    viewer_init()
</script>

<!-- MathJax -->

<!-- Katex -->

<!-- busuanzi  -->


<script src="/js/busuanzi-2.3.pure.min.js"></script>


<!-- ClickLove -->

<!-- ClickBoom1 -->

<!-- ClickBoom2 -->


<script src="/js/clickBoom2.js"></script>


<!-- CodeCopy -->


<link rel="stylesheet" href="/css/clipboard.css">

<script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script>
  function wait(callback, seconds) {
    var timelag = null;
    timelag = window.setTimeout(callback, seconds);
  }
  !function (e, t, a) {
    var initCopyCode = function(){
      var copyHtml = '';
      copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
      copyHtml += '<i class="ri-file-copy-2-line"></i><span>COPY</span>';
      copyHtml += '</button>';
      $(".highlight .code pre").before(copyHtml);
      $(".article pre code").before(copyHtml);
      var clipboard = new ClipboardJS('.btn-copy', {
        target: function(trigger) {
          return trigger.nextElementSibling;
        }
      });
      clipboard.on('success', function(e) {
        let $btn = $(e.trigger);
        $btn.addClass('copied');
        let $icon = $($btn.find('i'));
        $icon.removeClass('ri-file-copy-2-line');
        $icon.addClass('ri-checkbox-circle-line');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPIED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('ri-checkbox-circle-line');
          $icon.addClass('ri-file-copy-2-line');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
      clipboard.on('error', function(e) {
        e.clearSelection();
        let $btn = $(e.trigger);
        $btn.addClass('copy-failed');
        let $icon = $($btn.find('i'));
        $icon.removeClass('ri-file-copy-2-line');
        $icon.addClass('ri-time-line');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPY FAILED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('ri-time-line');
          $icon.addClass('ri-file-copy-2-line');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
    }
    initCopyCode();
  }(window, document);
</script>


<!-- CanvasBackground -->


<script src="/js/dz.js"></script>



    
  </div>
</body>

</html>